Si vous avez effectué une mise à niveau vers l'authentification Firebase avec Identity Platform, vous pouvez ajouter l'authentification multifacteur SMS à votre application iOS.
L'authentification multifacteur augmente la sécurité de votre application. Même si les attaquants compromettent souvent les mots de passe et les comptes sociaux, il est plus difficile d’intercepter un message texte.
Avant que tu commences
Activez au moins un fournisseur prenant en charge l’authentification multifacteur. Tous les fournisseurs prennent en charge MFA, à l'exception de l'authentification téléphonique, de l'authentification anonyme et d'Apple Game Center.
Assurez-vous que votre application vérifie les e-mails des utilisateurs. MFA nécessite une vérification par e-mail. Cela empêche les acteurs malveillants de s'inscrire à un service avec une adresse e-mail qui ne leur appartient pas, puis de verrouiller le véritable propriétaire en ajoutant un deuxième facteur.
Activation de l'authentification multifacteur
Ouvrez la page Authentification > Méthode de connexion de la console Firebase.
Dans la section Avancé , activez l'authentification multifacteur SMS .
Vous devez également saisir les numéros de téléphone avec lesquels vous testerez votre application. Bien que facultatif, l’enregistrement des numéros de téléphone de test est fortement recommandé pour éviter toute limitation pendant le développement.
Si vous n'avez pas encore autorisé le domaine de votre application, ajoutez-le à la liste verte sur la page Authentification > Paramètres de la console Firebase.
Vérifier votre application
Firebase doit vérifier que les demandes SMS proviennent de votre application. Vous pouvez le faire de deux manières :
Notifications APN silencieuses : lorsque vous connectez un utilisateur pour la première fois, Firebase peut envoyer une notification push silencieuse à l'appareil de l'utilisateur. L'authentification peut avoir lieu si l'application reçoit la notification. Notez qu'à partir d'iOS 8.0, vous n'avez pas besoin de demander à l'utilisateur d'autoriser les notifications push pour utiliser cette méthode.
Vérification reCAPTCHA : si vous ne pouvez pas envoyer de notification silencieuse (par exemple, parce que l'utilisateur a désactivé l'actualisation en arrière-plan ou que vous testez votre application dans le simulateur iOS), vous pouvez utiliser reCAPTCHA. Dans de nombreux cas, le reCAPTCHA se résoudra automatiquement sans aucune interaction de l'utilisateur.
Utiliser les notifications silencieuses
Pour activer les notifications APN à utiliser avec Firebase :
Dans Xcode, activez les notifications push pour votre projet.
Téléchargez votre clé d'authentification APNs à l'aide de la console Firebase (vos modifications seront automatiquement transférées vers Google Cloud Firebase). Si vous ne disposez pas déjà de votre clé d'authentification APN, consultez Configuration des APN avec FCM pour savoir comment l'obtenir.
Ouvrez la console Firebase .
Accédez à Paramètres du projet .
Sélectionnez l'onglet Messagerie cloud .
Sous Clé d'authentification APNs , dans la section Configuration de l'application iOS , cliquez sur Télécharger .
Sélectionnez votre clé.
Ajoutez l’ID de clé pour la clé. Vous pouvez trouver l'ID de clé sous Certificats, identifiants et profils dans le Centre des membres des développeurs Apple .
Cliquez sur Télécharger .
Si vous disposez déjà d'un certificat APNs, vous pouvez télécharger le certificat à la place.
Utiliser la vérification reCAPTCHA
Pour permettre au SDK client d'utiliser reCAPTCHA :
Ouvrez la configuration de votre projet dans Xcode.
Double-cliquez sur le nom du projet dans l'arborescence de gauche.
Sélectionnez votre application dans la section Cibles .
Sélectionnez l'onglet Informations .
Développez la section Types d'URL .
Cliquez sur le bouton + .
Saisissez votre ID client inversé dans le champ Schémas d'URL . Vous pouvez trouver cette valeur répertoriée dans le fichier de configuration
GoogleService-Info.plist
sous le nomREVERSED_CLIENT_ID
.
Une fois terminée, votre configuration devrait ressembler à ce qui suit :
En option, vous pouvez personnaliser la façon dont votre application présente le SFSafariViewController
ou UIWebView
lors de l'affichage du reCAPTCHA. Pour ce faire, créez une classe personnalisée conforme au protocole FIRAuthUIDelegate
et transmettez-la à verifyPhoneNumber:UIDelegate:completion:
.
Choisir un modèle d'inscription
Vous pouvez choisir si votre application nécessite une authentification multifacteur, ainsi que comment et quand inscrire vos utilisateurs. Certains modèles courants incluent :
Inscrivez le deuxième facteur de l'utilisateur dans le cadre de l'inscription. Utilisez cette méthode si votre application nécessite une authentification multifacteur pour tous les utilisateurs. Notez qu'un compte doit avoir une adresse e-mail vérifiée pour inscrire un deuxième facteur, votre flux d'inscription devra donc en tenir compte.
Offrez une option désactivable pour inscrire un deuxième facteur lors de l’inscription. Les applications qui souhaitent encourager, mais pas exiger, l’authentification multifacteur peuvent préférer cette approche.
Offrez la possibilité d'ajouter un deuxième facteur à partir de la page de gestion du compte ou du profil de l'utilisateur, au lieu de l'écran d'inscription. Cela minimise les frictions pendant le processus d'enregistrement, tout en rendant l'authentification multifacteur disponible pour les utilisateurs sensibles à la sécurité.
Exiger l'ajout d'un deuxième facteur de manière incrémentielle lorsque l'utilisateur souhaite accéder à des fonctionnalités présentant des exigences de sécurité accrues.
Inscription d'un deuxième facteur
Pour inscrire un nouveau facteur secondaire pour un utilisateur :
Réauthentifiez l'utilisateur.
Demandez à l'utilisateur de saisir son numéro de téléphone.
Obtenez une session multifacteur pour l'utilisateur :
Rapide
authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in // ... }
Objectif c
[authResult.user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session, NSError * _Nullable error) { // ... }];
Envoyez un message de vérification au téléphone de l'utilisateur. Assurez-vous que le numéro de téléphone est formaté avec un signe
+
et aucun autre signe de ponctuation ou espace (par exemple :+15105551234
).Rapide
// Send SMS verification code. PhoneAuthProvider.provider().verifyPhoneNumber( phoneNumber, uiDelegate: nil, multiFactorSession: session) { (verificationId, error) in // verificationId will be needed for enrollment completion. }
Objectif c
// Send SMS verification code. [FIRPhoneAuthProvider.provider verifyPhoneNumber:phoneNumber UIDelegate:nil multiFactorSession:session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { // verificationId will be needed for enrollment completion. }];
Bien que cela ne soit pas obligatoire, il est recommandé d'informer les utilisateurs à l'avance qu'ils recevront un message SMS et que les tarifs standard s'appliqueront.
La méthode
verifyPhoneNumber()
démarre le processus de vérification de l'application en arrière-plan à l'aide d'une notification push silencieuse. Si la notification push silencieuse n'est pas disponible, un défi reCAPTCHA est émis à la place.Une fois le code SMS envoyé, demandez à l'utilisateur de vérifier le code. Ensuite, utilisez leur réponse pour créer un
PhoneAuthCredential
:Rapide
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId, verificationCode: verificationCode)
Objectif c
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:kPhoneSecondFactorVerificationCode];
Initialisez un objet d'assertion :
Rapide
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
Objectif c
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
Complétez l'inscription. Vous pouvez éventuellement spécifier un nom d'affichage pour le deuxième facteur. Ceci est utile pour les utilisateurs ayant plusieurs seconds facteurs, puisque le numéro de téléphone est masqué pendant le flux d'authentification (par exemple, +1******1234).
Rapide
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in // ... }
Objectif c
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. [authResult.user.multiFactor enrollWithAssertion:assertion displayName:nil completion:^(NSError * _Nullable error) { // ... }];
Le code ci-dessous montre un exemple complet d'inscription d'un deuxième facteur :
Rapide
let user = Auth.auth().currentUser
user?.multiFactor.getSessionWithCompletion({ (session, error) in
// Send SMS verification code.
PhoneAuthProvider.provider().verifyPhoneNumber(
phoneNumber,
uiDelegate: nil,
multiFactorSession: session
) { (verificationId, error) in
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: phoneSecondFactorVerificationCode)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
user?.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
// ...
}
}
})
Objectif c
FIRUser *user = FIRAuth.auth.currentUser;
[user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
NSError * _Nullable error) {
// Send SMS verification code.
[FIRPhoneAuthProvider.provider
verifyPhoneNumber:phoneNumber
UIDelegate:nil
multiFactorSession:session
completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
[user.multiFactor enrollWithAssertion:assertion
displayName:displayName
completion:^(NSError * _Nullable error) {
// ...
}];
}];
}];
Toutes nos félicitations! Vous avez enregistré avec succès un deuxième facteur d'authentification pour un utilisateur.
Connecter les utilisateurs avec un deuxième facteur
Pour connecter un utilisateur avec une vérification SMS à deux facteurs :
Connectez l'utilisateur avec son premier facteur, puis détectez une erreur indiquant qu'une authentification multifacteur est requise. Cette erreur contient un résolveur, des indications sur les seconds facteurs inscrits et une session sous-jacente prouvant que l'utilisateur s'est authentifié avec succès avec le premier facteur.
Par exemple, si le premier facteur de l'utilisateur était un e-mail et un mot de passe :
Rapide
Auth.auth().signIn( withEmail: email, password: password ) { (result, error) in let authError = error as NSError if authError?.code == AuthErrorCode.secondFactorRequired.rawValue { // The user is a multi-factor user. Second factor challenge is required. let resolver = authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver // ... } else { // Handle other errors such as wrong password. } }
Objectif c
[FIRAuth.auth signInWithEmail:email password:password completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) { // User is not enrolled with a second factor and is successfully signed in. // ... } else { // The user is a multi-factor user. Second factor challenge is required. } }];
Si le premier facteur de l'utilisateur est un fournisseur fédéré, tel que OAuth, détectez l'erreur après avoir appelé
getCredentialWith()
.Si l’utilisateur a inscrit plusieurs facteurs secondaires, demandez-lui lequel utiliser. Vous pouvez obtenir le numéro de téléphone masqué avec
resolver.hints[selectedIndex].phoneNumber
et le nom d'affichage avecresolver.hints[selectedIndex].displayName
.Rapide
// Ask user which second factor to use. Then: if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID { // User selected a phone second factor. // ... } else if resolver.hints[selectedIndex].factorID == TotpMultiFactorID { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
Objectif c
FIRMultiFactorResolver *resolver = (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey]; // Ask user which second factor to use. Then: FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex]; if (hint.factorID == FIRPhoneMultiFactorID) { // User selected a phone second factor. // ... } else if (hint.factorID == FIRTOTPMultiFactorID) { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
Envoyez un message de vérification au téléphone de l'utilisateur :
Rapide
// Send SMS verification code. let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo PhoneAuthProvider.provider().verifyPhoneNumber( with: hint, uiDelegate: nil, multiFactorSession: resolver.session ) { (verificationId, error) in // verificationId will be needed for sign-in completion. }
Objectif c
// Send SMS verification code [FIRPhoneAuthProvider.provider verifyPhoneNumberWithMultiFactorInfo:hint UIDelegate:nil multiFactorSession:resolver.session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error != nil) { // Failed to verify phone number. } }];
Une fois le code SMS envoyé, demandez à l'utilisateur de vérifier le code et de l'utiliser pour construire un
PhoneAuthCredential
:Rapide
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId!, verificationCode: verificationCodeFromUser)
Objectif c
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:verificationCodeFromUser];
Initialisez un objet d'assertion avec les informations d'identification :
Rapide
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
Objectif c
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
Résolvez la connexion. Vous pouvez ensuite accéder au résultat de connexion d'origine, qui comprend les données standard spécifiques au fournisseur et les informations d'authentification :
Rapide
// Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(with: assertion) { (authResult, error) in // authResult will also contain the user, additionalUserInfo, optional // credential (null for email/password) associated with the first factor sign-in. // For example, if the user signed in with Google as a first factor, // authResult.additionalUserInfo will contain data related to Google provider that // the user signed in with. // user.credential contains the Google OAuth credential. // user.credential.accessToken contains the Google OAuth access token. // user.credential.idToken contains the Google OAuth ID token. }
Objectif c
// Complete sign-in. [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error != nil) { // User successfully signed in with the second factor phone number. } }];
Le code ci-dessous montre un exemple complet de connexion d'un utilisateur multifacteur :
Rapide
Auth.auth().signIn(
withEmail: email,
password: password
) { (result, error) in
let authError = error as NSError?
if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
let resolver =
authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
// Ask user which second factor to use.
// ...
// Then:
let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo
// Send SMS verification code
PhoneAuthProvider.provider().verifyPhoneNumber(
with: hint,
uiDelegate: nil,
multiFactorSession: resolver.session
) { (verificationId, error) in
if error != nil {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: verificationCodeFromUser)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete sign-in.
resolver.resolveSignIn(with: assertion) { (authResult, error) in
if error != nil {
// User successfully signed in with the second factor phone number.
}
}
}
}
}
Objectif c
[FIRAuth.auth signInWithEmail:email
password:password
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
// User is not enrolled with a second factor and is successfully signed in.
// ...
} else {
FIRMultiFactorResolver *resolver =
(FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
// Ask user which second factor to use.
// ...
// Then:
FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];
// Send SMS verification code
[FIRPhoneAuthProvider.provider
verifyPhoneNumberWithMultiFactorInfo:hint
UIDelegate:nil
multiFactorSession:resolver.session
completion:^(NSString * _Nullable verificationID,
NSError * _Nullable error) {
if (error != nil) {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider
credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete sign-in.
[resolver resolveSignInWithAssertion:assertion
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error != nil) {
// User successfully signed in with the second factor phone number.
}
}];
}];
}
}];
Toutes nos félicitations! Vous avez réussi à connecter un utilisateur à l’aide de l’authentification multifacteur.
Et après
- Gérez les utilisateurs multifacteur par programmation avec le SDK Admin.