[android] Phone auth implementation

This commit is contained in:
Chris Bianca 2017-08-25 12:16:23 +01:00
parent 93079c2f01
commit 81b631f111
4 changed files with 156 additions and 0 deletions

View File

@ -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 * confirmPasswordReset
* *

View File

@ -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;
}
}

View File

@ -1,6 +1,7 @@
// @flow // @flow
import User from './user'; import User from './user';
import ModuleBase from './../../utils/ModuleBase'; import ModuleBase from './../../utils/ModuleBase';
import ConfirmationResult from './ConfirmationResult';
// providers // providers
import EmailAuthProvider from './providers/Email'; import EmailAuthProvider from './providers/Email';
@ -8,6 +9,7 @@ import GoogleAuthProvider from './providers/Google';
import GithubAuthProvider from './providers/Github'; import GithubAuthProvider from './providers/Github';
import TwitterAuthProvider from './providers/Twitter'; import TwitterAuthProvider from './providers/Twitter';
import FacebookAuthProvider from './providers/Facebook'; import FacebookAuthProvider from './providers/Facebook';
import PhoneAuthProvider from './providers/Phone';
export default class Auth extends ModuleBase { export default class Auth extends ModuleBase {
static _NAMESPACE = 'auth'; 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 * Send reset password instructions via email
* @param {string} email The email to send password reset instructions * @param {string} email The email to send password reset instructions

View File

@ -0,0 +1,10 @@
export default {
credential(verificationId, code) {
return {
token: verificationId,
secret: code,
provider: 'phone',
providerId: 'phone',
};
},
};