Ajouter l'authentification multifacteur à votre application iOS
Ce document explique comment ajouter l'authentification multifacteur par SMS à votre application iOS.
L'authentification multifacteur renforce la sécurité de votre application. Bien que les pirates informatiques compromettent les mots de passe et les comptes de réseaux sociaux, l'interception des SMS est plus difficile.
Avant de commencer
Activez au moins un fournisseur compatible avec l'authentification multifacteur. Tous les fournisseurs acceptent l'authentification MFA, sauf l'authentification par téléphone, l'authentification anonyme et Apple Game Center.
Assurez-vous que votre application valide les adresses e-mail des utilisateurs. L'authentification multifacteur nécessite une validation de l'adresse e-mail. Cela empêche les utilisateurs malveillants de s'enregistrer à un service avec une adresse e-mail dont ils ne sont pas propriétaire, puis de bloquer le propriétaire réel en ajoutant un second facteur.
Activer l'authentification multifacteur
Accédez à la page MFA Identity Platform dans la console Google Cloud.
Accéder à la page MFADans la zone intitulée Authentification multifacteur par SMS, cliquez sur Activer.
Saisissez les numéros de téléphone avec lesquels vous souhaitez tester votre application. Bien que cette étape soit facultative, il est fortement recommandé d'enregistrer des numéros de téléphone de test pour éviter toute limitation lors du développement.
Si vous n'avez pas encore autorisé le domaine de votre application, ajoutez-le à la liste des autorisations en cliquant sur Ajouter un domaine à droite.
Cliquez sur Enregistrer.
Valider votre application
Identity Platform doit vérifier que les requêtes SMS proviennent de votre application. Pour cela, vous avez le choix entre deux méthodes :
Notifications APN silencieuses : lorsque vous connectez pour la première fois un utilisateur, Identity Platform peut envoyer une notification push silencieuse à l'appareil de l'utilisateur. L'authentification peut se poursuivre 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.
Validation 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, la méthode reCAPTCHA se résout automatiquement sans aucune interaction de l'utilisateur.
Utiliser les notifications silencieuses
Pour activer les notifications APN pour une utilisation avec Identity Platform, procédez comme suit :
Dans Xcode, activez les notifications push pour votre projet.
Importez votre clé d'authentification d'APN à l'aide de la console Firebase (vos modifications seront automatiquement transférées vers Google Cloud Identity Platform). Si vous ne possédez pas déjà votre clé d'authentification d'APN, consultez la page Configurer les APN avec FCM pour savoir comment l'obtenir.
Ouvrez la console Firebase.
Accédez aux Paramètres du projet.
Sélectionnez l'onglet Cloud Messaging.
Sous Clés d'authentification d'APN, dans la section Configuration de l'application iOS, cliquez sur Importer.
Sélectionnez votre clé.
Ajoutez l'ID de la clé. Vous pouvez trouver l'ID de clé sous Certificats, identifiants et profils dans Apple Developer Member Center.
Cliquez sur Importer.
Si vous disposez déjà d'un certificat APN, vous pouvez l'importer à la place.
Utiliser la validation 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 Infos.
Développez la section Types d'URL.
Cliquez sur le bouton +.
Saisissez votre ID client inversé dans le champ Schémas d'URL. Cette valeur est répertoriée dans le fichier de configuration
GoogleService-Info.plist
sous la formeREVERSED_CLIENT_ID
.
Une fois terminée, votre configuration ressemble normalement à ce qui suit :
Vous pouvez éventuellement personnaliser la manière dont votre application présente SFSafariViewController
ou UIWebView
lors de l'affichage de 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 décider si votre application nécessite une authentification multifacteur, et comment et quand inscrire vos utilisateurs. Voici quelques modèles courants :
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 disposer d'une adresse e-mail validée pour enregistrer un deuxième facteur. Votre parcours d'enregistrement doit donc tenir compte de ce point.
Proposez une option désactivable pour inscrire un second facteur lors de l'enregistrement. Les applications qui souhaitent encourager mais pas exiger l'authentification multifacteur peuvent préférer cette approche.
Offrez la possibilité d'ajouter un second facteur à partir de la page de gestion de compte ou de profil de l'utilisateur, au lieu de l'écran d'inscription. Cela minimise les frictions lors du processus d'enregistrement tout en rendant encore l'authentification multifacteur disponible pour les utilisateurs sensibles à la sécurité.
Exigez l'ajout incrémentiel d'un second facteur lorsque l'utilisateur souhaite accéder aux fonctionnalités présentant des exigences de sécurité accrues.
Inscrire un second facteur
Pour inscrire un nouveau facteur secondaire pour un utilisateur, procédez comme suit :
Réauthentifiez l'utilisateur.
Demandez à l'utilisateur de saisir son numéro de téléphone.
Obtenez une session multifacteur pour l'utilisateur :
Swift
authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in // ... }
Objective-C
[authResult.user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session, NSError * _Nullable error) { // ... }];
Envoyez un message de validation sur le téléphone de l'utilisateur. Assurez-vous que le numéro de téléphone est au format
+
au début, sans autre signe de ponctuation ni espace (par exemple:+15105551234
).Swift
// Send SMS verification code. PhoneAuthProvider.provider().verifyPhoneNumber( phoneNumber, uiDelegate: nil, multiFactorSession: session) { (verificationId, error) in // verificationId will be needed for enrollment completion. }
Objective-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 préalablement les utilisateurs qu'ils recevront un SMS, et que les tarifs standards s'appliquent.
La méthode
verifyPhoneNumber()
lance le processus de validation d'application en arrière-plan à l'aide de la notification push silencieuse. Si la notification push silencieuse n'est pas disponible, un test reCAPTCHA est émis à la place.Une fois le code SMS envoyé, demandez à l'utilisateur de le vérifier. Utilisez ensuite sa réponse pour créer un
PhoneAuthCredential
:Swift
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId, verificationCode: verificationCode)
Objective-C
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:kPhoneSecondFactorVerificationCode];
Initialisez un objet d'assertion :
Swift
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
Objective-C
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
Terminez l'inscription. Vous pouvez éventuellement spécifier un nom à afficher pour le deuxième facteur. Cela s'avère utile pour les utilisateurs qui ont plusieurs facteurs, car le numéro de téléphone est masqué pendant le processus d'authentification (par exemple, +1******1234).
Swift
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in // ... }
Objective-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 second facteur :
Swift
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
// ...
}
}
})
Objective-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) {
// ...
}];
}];
}];
Félicitations ! Vous avez enregistré un second facteur d'authentification pour un utilisateur.
Connecter des utilisateurs avec un second facteur
Pour connecter un utilisateur via la validation SMS à deux facteurs, procédez comme suit :
Connectez l'utilisateur avec son premier facteur, puis détectez une erreur indiquant que l'authentification multifacteur est requise. Cette erreur contient un résolveur, des indices sur les seconds facteurs inscrits et une session sous-jacente attestant que l'utilisateur s'est authentifié avec succès avec le premier facteur.
Par exemple, si le premier facteur de l'utilisateur est une adresse e-mail et un mot de passe :
Swift
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. } }
Objective-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 qu'OAuth, détectez l'erreur après avoir appelé
getCredentialWith()
.Si l'utilisateur possède plusieurs facteurs secondaires inscrits, demandez-lui lequel utiliser. Vous pouvez obtenir le numéro de téléphone masqué avec
resolver.hints[selectedIndex].phoneNumber
et le nom à afficher avecresolver.hints[selectedIndex].displayName
.Swift
// 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. }
Objective-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 validation sur le téléphone de l'utilisateur :
Swift
// 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. }
Objective-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 le vérifier et de l'utiliser pour créer un
PhoneAuthCredential
:Swift
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId!, verificationCode: verificationCodeFromUser)
Objective-C
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:verificationCodeFromUser];
Initialisez un objet d'assertion avec l'identifiant :
Swift
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
Objective-C
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
Résolvez la connexion. Vous pouvez ensuite accéder au résultat de connexion d'origine, qui inclut les données spécifiques au fournisseur et les identifiants d'authentification :
Swift
// 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. }
Objective-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 illustre un exemple complet de connexion d'un utilisateur multifacteur :
Swift
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.
}
}
}
}
}
Objective-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.
}
}];
}];
}
}];
Félicitations ! Vous avez connecté un utilisateur à l'aide de l'authentification multifacteur.
Étape suivante
- Gérez les utilisateurs multifacteur par programmation à l'aide du SDK Admin.