[android] Phone auth implementation
This commit is contained in:
parent
93079c2f01
commit
81b631f111
|
@ -561,6 +561,108 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* signInWithPhoneNumber
|
||||
*
|
||||
* @param appName
|
||||
* @param phoneNumber
|
||||
*/
|
||||
@ReactMethod
|
||||
public void signInWithPhoneNumber(String appName, final String phoneNumber, final Promise promise) {
|
||||
Log.d(TAG, "signInWithPhoneNumber");
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
|
||||
// Reset the verification Id
|
||||
mVerificationId = null;
|
||||
|
||||
PhoneAuthProvider.getInstance(firebaseAuth).verifyPhoneNumber(phoneNumber, 60, TimeUnit.SECONDS,
|
||||
mReactContext.getCurrentActivity(), new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
|
||||
private boolean promiseResolved = false;
|
||||
|
||||
@Override
|
||||
public void onVerificationCompleted(final PhoneAuthCredential phoneAuthCredential) {
|
||||
// User has been automatically verified, log them in
|
||||
firebaseAuth.signInWithCredential(phoneAuthCredential)
|
||||
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<AuthResult> task) {
|
||||
if (task.isSuccessful()) {
|
||||
// onAuthStateChanged will pick up the user change
|
||||
Log.d(TAG, "signInWithPhoneNumber:autoVerified:signInWithCredential:onComplete:success");
|
||||
// To ensure that there is no hanging promise, we resolve it with a null verificationId
|
||||
// as calling ConfirmationResult.confirm(code) is invalid in this case anyway
|
||||
if (!promiseResolved) {
|
||||
WritableMap verificationMap = Arguments.createMap();
|
||||
verificationMap.putNull("verificationId");
|
||||
promise.resolve(verificationMap);
|
||||
}
|
||||
} else {
|
||||
// With phone auth, the credential will only every be rejected if the user
|
||||
// account linked to the phone number has been disabled
|
||||
Exception exception = task.getException();
|
||||
Log.e(TAG, "signInWithPhoneNumber:autoVerified:signInWithCredential:onComplete:failure", exception);
|
||||
if (promiseResolved) {
|
||||
// In the scenario where an SMS code has been sent, we have no way to report
|
||||
// back to the front-end that as the promise has already been used
|
||||
} else {
|
||||
promiseRejectAuthException(promise, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVerificationFailed(FirebaseException e) {
|
||||
// This callback is invoked in an invalid request for verification is made,
|
||||
// e.g. phone number format is incorrect, or the SMS quota for the project
|
||||
// has been exceeded
|
||||
Log.d(TAG, "signInWithPhoneNumber:verification:failed");
|
||||
promiseRejectAuthException(promise, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
|
||||
// TODO: This isn't being saved anywhere if the activity gets restarted when going to the SMS app
|
||||
mVerificationId = verificationId;
|
||||
WritableMap verificationMap = Arguments.createMap();
|
||||
verificationMap.putString("verificationId", verificationId);
|
||||
promise.resolve(verificationMap);
|
||||
promiseResolved = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCodeAutoRetrievalTimeOut(String verificationId) {
|
||||
super.onCodeAutoRetrievalTimeOut(verificationId);
|
||||
// Purposefully not doing anything with this at the moment
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void _confirmVerificationCode(String appName, final String verificationCode, final Promise promise) {
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
|
||||
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, verificationCode);
|
||||
|
||||
firebaseAuth.signInWithCredential(credential)
|
||||
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<AuthResult> task) {
|
||||
if (task.isSuccessful()) {
|
||||
Log.d(TAG, "_confirmVerificationCode:signInWithCredential:onComplete:success");
|
||||
promiseWithUser(task.getResult().getUser(), promise);
|
||||
} else {
|
||||
Exception exception = task.getException();
|
||||
Log.e(TAG, "_confirmVerificationCode:signInWithCredential:onComplete:failure", exception);
|
||||
promiseRejectAuthException(promise, exception);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* confirmPasswordReset
|
||||
*
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* @url https://firebase.google.com/docs/reference/js/firebase.User
|
||||
*/
|
||||
export default class ConfirmationResult {
|
||||
_auth: Object;
|
||||
_verificationId: string;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param auth
|
||||
* @param verificationId The phone number authentication operation's verification ID.
|
||||
*/
|
||||
constructor(auth: Object, verificationId: string) {
|
||||
this._auth = auth;
|
||||
this._verificationId = verificationId;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param verificationCode
|
||||
* @return {*}
|
||||
*/
|
||||
confirm(verificationCode: string): Promise<Object> {
|
||||
return this._auth._interceptUserValue(
|
||||
this._auth._native._confirmVerificationCode(verificationCode)
|
||||
);
|
||||
}
|
||||
|
||||
get verificationId(): String | null {
|
||||
return _verificationId;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
import User from './user';
|
||||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import ConfirmationResult from './ConfirmationResult';
|
||||
|
||||
// providers
|
||||
import EmailAuthProvider from './providers/Email';
|
||||
|
@ -8,6 +9,7 @@ import GoogleAuthProvider from './providers/Google';
|
|||
import GithubAuthProvider from './providers/Github';
|
||||
import TwitterAuthProvider from './providers/Twitter';
|
||||
import FacebookAuthProvider from './providers/Facebook';
|
||||
import PhoneAuthProvider from './providers/Phone';
|
||||
|
||||
export default class Auth extends ModuleBase {
|
||||
static _NAMESPACE = 'auth';
|
||||
|
@ -146,6 +148,16 @@ export default class Auth extends ModuleBase {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously signs in using a phone number.
|
||||
*
|
||||
*/
|
||||
signInWithPhoneNumber(phoneNumber: string): Promise<Object> {
|
||||
return this._native.signInWithPhoneNumber(phoneNumber).then((result) => {
|
||||
return new ConfirmationResult(this, result.verificationId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send reset password instructions via email
|
||||
* @param {string} email The email to send password reset instructions
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
export default {
|
||||
credential(verificationId, code) {
|
||||
return {
|
||||
token: verificationId,
|
||||
secret: code,
|
||||
provider: 'phone',
|
||||
providerId: 'phone',
|
||||
};
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue