Pour un projet client, je crée une application hybride simple qui remplit une fonction très simple tout en générant un trafic important. L’application n’aurait normalement pas besoin d’un backend, car c’est très simple, et firebase apparaît comme une solution parfaite pour le projet.
La seule partie où je suis bloqué est SMS Vérification/Authentification avec Firebase. Cependant, après des recherches intenses sur Google et sur le doc, je me suis rendu compte qu'il n'y avait pas de moyen facile de le faire. Voici ce que j'ai examiné jusqu'à présent:
Généralement, avec les applications mobiles hybrides, c'est leur nature non native ou les API JS qui sont à blâmer, mais pour la première fois (pour moi du moins), on a l'impression que ce n'est pas le cas. À ce stade, je suppose que Firebase n’est pas une option valable, mais je voulais demander une dernière fois aux membres aimants et attentionnés de la communauté avant de commencer à examiner AWS et à mettre en place un backend complet pour le client.
Existe-t-il un autre moyen de gérer ce type d'authentification sans le service intermédiaire/sans serveur principal? Quelqu'un a-t-il déjà utilisé ces solutions?
MISE À JOUR: MAI 2017
La vérification et l'authentification du téléphone sont désormais disponibles de manière native dans Firebase. Voir ma réponse affichée ci-dessous.
MISE À JOUR: AVR 2017
Firebase supporte maintenant nativement Fonctions Cloud . Vous pouvez maintenant accomplir ceci et bien plus encore en utilisant Cloud Functions sans configurer de serveur.
MISE À JOUR: OCT 2017
Fabric.io et Firebase ont collaboré et intégré Les chiffres dans l'authentification téléphonique Firebase et ont lancé davantage de fonctionnalités pour Fabric.
Depuis le 17 mai 2017, les gens formidables chez Firebase ont intégré l'authentification téléphonique de Digits dans Firebase. C’est maintenant incroyablement facile à réaliser en mode natif dans Firebase , plus ou moins avec l’aiguillage d’un commutateur et sans le recours à un service externe ou similaire. Vous pouvez en savoir plus à ce sujet dans la documentation :)
Je ne peux pas parler de toutes les intégrations que vous avez mentionnées, mais vous voudrez peut-être essayer un autre service de Twilio, Authy.
Nous avons récemment publié des exemples de code prêts à la production via des tutoriels pour aider les utilisateurs à résoudre ce type de problèmes.
Un tel exemple vous guide à travers:
est le 2FA avec Authy tutorial . L'extrait de code Node.js suivant montre le noeud final en attente d'approbation ou de refus du statut de l'utilisateur. Si l'utilisateur a approuvé la demande One Touch, nous enregistrons sa session sous le nom confirmed
, qui les connecte officiellement.
Si la demande est refusée, nous affichons la page /verify
et demandons à l'utilisateur de se connecter avec un jeton.
// Internal endpoint for checking the status of OneTouch
exports.authyStatus = function(request, response) {
var status = (request.user) ? request.user.authyStatus : 'unverified';
if (status == 'approved') {
request.session.confirmed = true;
request.session.save(function(err) {
if (err) return error(response, 500,
'There was an error validating your session.');
});
}
if (!request.session) {
return error(response, 404, 'No valid session found for this user.');
} else {
response.send({ status: status });
}
};
Donc, cela nécessite en effet que vous ayez un serveur. Toutefois, si vous avez choisi cet exemple, cela devrait vous aider à décider de ce qui fonctionnera le mieux pour votre application.
import Android.app.Activity;
import Android.os.Bundle;
import Android.support.annotation.NonNull;
import Android.text.TextUtils;
import Android.util.Log;
import Android.widget.EditText;
import Android.widget.Toast;
import com.google.Android.gms.tasks.OnCompleteListener;
import com.google.Android.gms.tasks.Task;
import com.google.firebase.FirebaseException;
import com.google.firebase.FirebaseTooManyRequestsException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import Java.util.concurrent.TimeUnit;
public class PhoneAutenticationService {
public PhoneAutenticationService(Activity activity,FirebaseAuth auth) {
this.activity = activity;
this.mAuth = auth;
setupCallback();
}
private static final String TAG = PhoneAutenticationService.class.getSimpleName();
private Activity activity;
private String verificationCode;
private static final String KEY_VERIFY_IN_PROGRESS = "key_verify_in_progress";
private static final int STATE_INITIALIZED = 1;
private static final int STATE_CODE_SENT = 2;
private static final int STATE_VERIFY_FAILED = 3;
private static final int STATE_VERIFY_SUCCESS = 4;
private static final int STATE_SIGNIN_FAILED = 5;
private static final int STATE_SIGNIN_SUCCESS = 6;
// [START declare_auth]
private FirebaseAuth mAuth;
// [END declare_auth]
private boolean mVerificationInProgress = false;
private String mVerificationId;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private PhoneAuthProvider.ForceResendingToken mResendToken;
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_VERIFY_IN_PROGRESS, mVerificationInProgress);
}
protected void onRestoreInstanceState(Bundle savedInstanceState) {
mVerificationInProgress = savedInstanceState.getBoolean(KEY_VERIFY_IN_PROGRESS);
}
// [START on_start_check_user]
public void onStart(EditText mPhoneNumberField) {
// Check if user is signed in (non-null) and update UI accordingly.
FirebaseUser currentUser = mAuth.getCurrentUser();
updateUI(currentUser);
// [START_EXCLUDE]
if (mVerificationInProgress && validatePhoneNumber(mPhoneNumberField)) {
startPhoneNumberVerification(mPhoneNumberField.getText().toString());
}
// [END_EXCLUDE]
}
// [END on_start_check_user]
private void setupCallback(){
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verificaiton without
// user action.
Log.d(TAG, "onVerificationCompleted:" + credential);
// [START_EXCLUDE silent]
mVerificationInProgress = false;
// [END_EXCLUDE]
// [START_EXCLUDE silent]
// Update the UI and attempt sign in with the phone credential
updateUI(STATE_VERIFY_SUCCESS, credential);
// [END_EXCLUDE]
signInWithPhoneAuthCredential(credential);
}
@Override
public void onVerificationFailed(FirebaseException e) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
Log.w(TAG, "onVerificationFailed", e);
// [START_EXCLUDE silent]
mVerificationInProgress = false;
// [END_EXCLUDE]
if (e instanceof FirebaseAuthInvalidCredentialsException) {
// Invalid request
// [START_EXCLUDE]
Toast.makeText(activity,"Invalid phone number.",Toast.LENGTH_SHORT).show();
// [END_EXCLUDE]
} else if (e instanceof FirebaseTooManyRequestsException) {
// The SMS quota for the project has been exceeded
// [START_EXCLUDE]
Toast.makeText(activity,"Quota exceeded.",Toast.LENGTH_SHORT).show();
// [END_EXCLUDE]
}
// Show a message and update the UI
// [START_EXCLUDE]
updateUI(STATE_VERIFY_FAILED);
// [END_EXCLUDE]
}
@Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token) {
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
Log.d(TAG, "onCodeSent:" + verificationId);
Toast.makeText(activity,"onCodeSent:" + verificationId,Toast.LENGTH_SHORT).show();
verificationCode = verificationId;
// Save verification ID and resending token so we can use them later
mVerificationId = verificationId;
setVerificationCode(verificationId);
mResendToken = token;
// [START_EXCLUDE]
// Update UI
updateUI(STATE_CODE_SENT);
// [END_EXCLUDE]
}
};
}
public void startPhoneNumberVerification(String phoneNumber) {
// [START start_phone_auth]
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
activity, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
// [END start_phone_auth]
mVerificationInProgress = true;
}
public void verifyPhoneNumberWithCode(String verificationId, String code) {
// [START verify_with_code]
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
// [END verify_with_code]
signInWithPhoneAuthCredential(credential);
}
// [START resend_verification]
public void resendVerificationCode(String phoneNumber,
PhoneAuthProvider.ForceResendingToken token) {
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
activity, // Activity (for callback binding)
mCallbacks); // resending
// [END start_phone_auth]
}
// [END resend_verification]
// [START sign_in_with_phone]
public void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success");
Toast.makeText(activity,"signInWithCredential:success",Toast.LENGTH_SHORT).show();
FirebaseUser user = task.getResult().getUser();
// [START_EXCLUDE]
updateUI(STATE_SIGNIN_SUCCESS, user);
// [END_EXCLUDE]
} else {
// Sign in failed, display a message and update the UI
Log.w(TAG, "signInWithCredential:failure", task.getException());
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
// The verification code entered was invalid
// [START_EXCLUDE silent]
Toast.makeText(activity,"Invalid code.",Toast.LENGTH_SHORT).show();
// [END_EXCLUDE]
}
// [START_EXCLUDE silent]
// Update UI
updateUI(STATE_SIGNIN_FAILED);
// [END_EXCLUDE]
}
}
});
}
// [END sign_in_with_phone]
public void signOut() {
mAuth.signOut();
updateUI(STATE_INITIALIZED);
}
private void updateUI(int uiState) {
updateUI(uiState, mAuth.getCurrentUser(), null);
}
public void updateUI(FirebaseUser user) {
if (user != null) {
updateUI(STATE_SIGNIN_SUCCESS, user);
} else {
updateUI(STATE_INITIALIZED);
}
}
private void updateUI(int uiState, FirebaseUser user) {
updateUI(uiState, user, null);
}
private void updateUI(int uiState, PhoneAuthCredential cred) {
updateUI(uiState, null, cred);
}
private void updateUI(int uiState, FirebaseUser user, PhoneAuthCredential cred) {
switch (uiState) {
case STATE_INITIALIZED:
// Initialized state, show only the phone number field and start button
Toast.makeText(activity,"Initialized state",Toast.LENGTH_SHORT).show();
break;
case STATE_CODE_SENT:
// Code sent state, show the verification field, the
Toast.makeText(activity,"Code sent state",Toast.LENGTH_SHORT).show();
break;
case STATE_VERIFY_FAILED:
// Verification has failed, show all options
Toast.makeText(activity,"Verification has failed",Toast.LENGTH_SHORT).show();
break;
case STATE_VERIFY_SUCCESS:
// Verification has succeeded, proceed to firebase sign in
Toast.makeText(activity,"Verification has succeeded",Toast.LENGTH_SHORT).show();
// Set the verification text based on the credential
if (cred != null) {
if (cred.getSmsCode() != null) {
//mVerificationField.setText(cred.getSmsCode());
} else {
Toast.makeText(activity,"Invalid verification code.",Toast.LENGTH_SHORT).show();
}
}
break;
case STATE_SIGNIN_FAILED:
// No-op, handled by sign-in check
Toast.makeText(activity,"Sign in failed",Toast.LENGTH_SHORT).show();
break;
case STATE_SIGNIN_SUCCESS:
// Np-op, handled by sign-in check
Toast.makeText(activity,"Sign in sucesssss!!!!",Toast.LENGTH_SHORT).show();
break;
}
if (user == null) {
// Signed out
} else {
// Signed in
}
}
public boolean validatePhoneNumber(EditText mPhoneNumberField) {
String phoneNumber = mPhoneNumberField.getText().toString();
if (TextUtils.isEmpty(phoneNumber) || phoneNumber.length()>10 || phoneNumber.length()<9) {
Toast.makeText(activity,"Invalid phone number.",Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
public PhoneAuthProvider.OnVerificationStateChangedCallbacks getmCallbacks() {
return mCallbacks;
}
public PhoneAuthProvider.ForceResendingToken getmResendToken() {
return mResendToken;
}
public FirebaseAuth getmAuth() {
return mAuth;
}
public String getVerificationCode() {
return verificationCode;
}
public void setVerificationCode(String verificationCode) {
this.verificationCode = verificationCode;
}
}
Dans votre activité, initialisez Firebase auth et listener.
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
//init all auth process
phoneAutenticationService = new PhoneAutenticationService(this,mAuth);
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
getActivity().registerReceiver(smsBroadcastReceiver, filter);// define e broadcast receiver to intercept a sms verification code
}
@Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);sms code
}
getActivity().unregisterReceiver(smsBroadcastReceiver);
}
et enfin appelez la méthode firebase pour l'authentification
public void startAuthenticationByPhone(){
if (!validatePhoneNumber(phoneInput)) {
return;
}
startPhoneNumberVerification(phoneInput.getText().toString());
}......
Désormais, l'authentification téléphonique est disponible dans firebase.Voici le code d'authentification téléphonique utilisant Firebase:
EditText phoneNum,Code;// two edit text one for enter phone number other for enter OTP code
Button sent_,Verify;// sent button to request for verification and verify is for to verify code
private PhoneAuthProvider.ForceResendingToken mResendToken;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private FirebaseAuth mAuth;
private String mVerificationId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone_number_auth);
phoneNum =(EditText) findViewById(R.id.fn_num);
Code =(EditText) findViewById(R.id.code);
sent_ =(Button)findViewById(R.id.sent_nu);
Verify =(Button)findViewById(R.id.verify);
callback_verificvation(); ///function initialization
mAuth = FirebaseAuth.getInstance();
sent_.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String num=phoneNum.getText().toString();
startPhoneNumberVerification(num); // call function for receive OTP 6 digit code
}
});
Verify.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String code=Code.getText().toString();
verifyPhoneNumberWithCode(mVerificationId,code); //call function for verify code
}
});
}
private void startPhoneNumberVerification(String phoneNumber) {
// [START start_phone_auth]
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
this, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
// [END start_phone_auth]
}
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
FirebaseUser user = task.getResult().getUser();
Toast.makeText(getApplicationContext(), "sign in successfull", Toast.LENGTH_SHORT).show();
} else {
// Sign in failed, display a message and update the UI
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
// The verification code entered was invalid
}
}
}
});
}
private void verifyPhoneNumberWithCode(String verificationId, String code) {
// [START verify_with_code]
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
// [END verify_with_code]
signInWithPhoneAuthCredential(credential);
}
private void callback_verificvation() {
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verificaiton without
// user action.
signInWithPhoneAuthCredential(credential);
}
@Override
public void onVerificationFailed(FirebaseException e) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
if (e instanceof FirebaseAuthInvalidCredentialsException) {
// Invalid request
} else if (e instanceof FirebaseTooManyRequestsException) {
// The SMS quota for the project has been exceeded
}
// Show a message and update the UI
}
@Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token) {
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
// Save verification ID and resending token so we can use them later
mVerificationId = verificationId;
mResendToken = token;
}
};