Tutoriel : ajouter une fonctionnalité de connexion et de déconnexion dans une application iOS/macOS en utilisant l’authentification native
S’applique à : iOS (Swift) macOS (Swift)
Ce tutoriel montre comment connecter et déconnecter un utilisateur dans votre application mobile iOS/macOS avec un code secret à usage unique envoyé par e-mail ou un nom d’utilisateur et un mot de passe en utilisant l’authentification native.
Dans ce tutoriel, vous allez apprendre à :
- Connecter un utilisateur avec un code secret à usage unique envoyé par e-mail ou un nom d’utilisateur (e-mail) et un mot de passe.
- Déconnecter un utilisateur.
- Gérer l’erreur de connexion
Prérequis
- Tutoriel : préparer votre application iOS/macOS pour l’authentification native.
- Si vous souhaitez vous connecter à l’aide de Adresse e-mail et mot de passe, configurez votre flux d’utilisateur pour qu’il utilise Adresse e-mail et mot de passe lorsque vous créez votre flux d’utilisateur d’inscription et de connexion.
Connecter un utilisateur
Pour connecter un utilisateur via le flux Envoyer un code secret à usage unique par e-mail, capturez l’adresse e-mail et envoyez un e-mail contenant un code secret à usage unique pour que l’utilisateur vérifie son e-mail. Lorsque l’utilisateur entre un code secret à usage unique valide, l’application le connecte.
Pour connecter un utilisateur à l’aide du flux Adresse e-mail et mot de passe, capturez l’e-mail et le mot de passe. Si le nom d’utilisateur et le mot de passe sont valides, l’application connecte l’utilisateur.
Pour connecter un utilisateur, vous devez :
Créer une interface utilisateur pour :
- Collecter une adresse e-mail de l’utilisateur. Ajouter une validation à vos entrées pour vérifier que l’utilisateur entre une adresse e-mail valide.
- Collecter un mot de passe si vous vous inscrivez avec un nom d’utilisateur (e-mail) et un mot de passe.
- Collectez un code secret à usage unique par e-mail auprès de l’utilisateur si vous vous connectez avec un code secret à usage unique.
- Ajoutez un bouton pour permettre à l’utilisateur de renvoyer un code secret à usage unique si vous vous connectez avec l’envoi par e-mail de code secret à usage unique.
Dans votre IU, ajoutez un bouton dont l’événement de sélection démarre une connexion, comme indiqué dans l’extrait de code suivant :
@IBAction func signInPressed(_: Any) { guard let email = emailTextField.text else { resultTextView.text = "email not set" return } nativeAuth.signIn(username: email, delegate: self) }
Pour connecter un utilisateur à l’aide du flux Envoyer par e-mail un code secret à usage unique, nous utilisons l’extrait de code suivant :
nativeAuth.signIn(username: email, delegate: self)
La méthode
signIn(username:delegate)
, qui répond de manière asynchrone en appelant l’une des méthodes sur l’objet délégué transmis, doit implémenter le protocoleSignInStartDelegate
. Nous transmettons l’adresse e-mail que l’utilisateur fournit dans le formulaire de soumission par e-mail et transmettonsself
en tant que délégués.Pour connecter un utilisateur à l’aide du flux Adresse e-mail et mot de passe, utilisez les extraits de code suivants :
nativeAuth.signIn(username: email, password: password, delegate: self)
Dans la méthode
signIn(username:password:delegate)
, vous transmettez l’adresse e-mail que l’utilisateur nous a fournie, son mot de passe et transmettez l’objet délégué conforme au protocoleSignInStartDelegate
. Pour cet exemple, nous transmettonsself
.Pour implémenter le protocole
SignInStartDelegate
lorsque vous utilisez le flux Envoyer par e-mail un code secret à usage unique, utilisez l’extrait de code suivant :extension ViewController: SignInStartDelegate { func onSignInStartError(error: MSAL.SignInStartError) { resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")" } func onSignInCodeRequired( newState: MSAL.SignInCodeRequiredState, sentTo: String, channelTargetType: MSAL.MSALNativeAuthChannelType, codeLength: Int ) { resultTextView.text = "Verification code sent to \(sentTo)" } }
La
signIn(username:delegate)
entraîne un appel aux méthodes déléguées. Dans le scénario le plus probable, la méthodeonSignInCodeRequired(newState:sentTo:channelTargetType:codeLength)
est appelée pour indiquer qu’un code a été envoyé pour vérifier l’adresse e-mail de l’utilisateur. Outre les détails de l’emplacement depuis lequel le code a été envoyé et le nombre de chiffres qu’il contient, cette méthode déléguée dispose également d’unnewState
paramètre de typeSignInCodeRequiredState
, ce qui nous donne accès aux deux nouvelles méthodes suivantes :submitCode(code:delegate)
resendCode(delegate)
Utilisez la méthode
submitCode(code:delegate)
pour envoyer le code secret à usage unique fourni par l’utilisateur sous forme de code secret à usage unique, utilisez l’extrait de code suivant :newState.submitCode(code: userSuppliedCode, delegate: self)
La
submitCode(code:delegate)
accepte le mot de passe unique et le paramètre délégué. Après avoir envoyé le code, vous devez vérifier le code secret à usage unique en implémentant le protocoleSignInVerifyCodeDelegate
.Pour implémenter le protocole
SignInVerifyCodeDelegate
en tant qu’extension de votre classe, utilisez l’extrait de code suivant :extension ViewController: SignInVerifyCodeDelegate { func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) { resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")" } func onSignInCompleted(result: MSALNativeAuthUserAccountResult) { resultTextView.text = "Signed in successfully." result.getAccessToken(delegate: self) } }
Dans le scénario le plus courant, nous recevons un appel à
onSignInCompleted(result)
indiquant que l’utilisateur s’est connecté. Le résultat peut être utilisé pour récupéreraccess token
.La méthode
getAccessToken(delegate)
accepte un paramètre délégué et nous devons implémenter les méthodes requises dans le protocoleCredentialsDelegate
.Dans le scénario le plus courant, nous recevons un appel à
onAccessTokenRetrieveCompleted(result)
indiquant que l’utilisateur a obtenu unaccess token
.extension ViewController: CredentialsDelegate { func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) { resultTextView.text = "Error retrieving access token" } func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) { resultTextView.text = "Signed in. Access Token: \(result.accessToken)" } }
Pour implémenter le protocole
SignInStartDelegate
lorsque vous utilisez le flux Adresse e-mail et mot de passe, utilisez l’extrait de code suivant :extension ViewController: SignInStartDelegate { func onSignInStartError(error: MSAL.SignInStartError) { resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")" } func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) { // User successfully signed in } }
Dans le scénario le plus courant, nous recevons un appel à
onSignInCompleted(result)
indiquant que l’utilisateur s’est connecté. Le résultat peut être utilisé pour récupéreraccess token
.La méthode
getAccessToken(delegate)
accepte un paramètre délégué et nous devons implémenter les méthodes requises dans le protocoleCredentialsDelegate
.Dans le scénario le plus courant, nous recevons un appel à
onAccessTokenRetrieveCompleted(result)
indiquant que l’utilisateur a obtenu unaccess token
.extension ViewController: CredentialsDelegate { func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) { resultTextView.text = "Error retrieving access token" } func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) { resultTextView.text = "Signed in. Access Token: \(result.accessToken)" } }
Gérer les erreurs de connexion
Lors de la connexion, certaines actions peuvent échouer. Par exemple, l’utilisateur peut tenter de se connecter avec une adresse e-mail qui n’existe pas ou s’il envoie un code non valide.
Pour gérer les erreurs dans la méthode
signIn(username)
ousignIn(username, password)
, utilisez l’extrait de code suivant :func onSignInStartError(error: MSAL.SignInStartError) { if error.isUserNotFound || error.isInvalidUsername { resultTextView.text = "Invalid username" } else { resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")" } }
Pour gérer les erreurs de la méthode
submitCode()
, utilisez l’extrait de code suivant :func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) { if error.isInvalidCode { // Inform the user that the submitted code was incorrect and ask for a new code to be supplied let userSuppliedCode = retrieveNewCode() newState?.submitCode(code: userSuppliedCode, delegate: self) } else { resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")" } }
Si l’utilisateur entre un code de vérification d’e-mail incorrect, le gestionnaire d’erreurs inclut une référence à un
SignInCodeRequiredState
qui peut être utilisé pour envoyer un nouveau code mis à jour. Dans notre implémentation antérieure du protocoleSignInVerifyCodeDelegate
, nous n’affichions l’erreur que lorsque nous gérions la fonctiononSignInVerifyCodeError(error:newState)
déléguée.
Lire les revendications de jeton d’ID
Une fois que votre application a acquis un jeton d’ID, vous pouvez récupérer les revendications associées au compte actif. Pour ce faire, utilisez l’extrait de code suivant :
func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
let claims = result.account.accountClaims
let preferredUsername = claims?["preferred_username"] as? String
}
La clé que vous utilisez pour accéder à la valeur de revendication est le nom que vous spécifiez quand vous ajoutez l’attribut utilisateur en tant que revendication de jeton.
Découvrez comment ajouter des attributs intégrés et personnalisés aux revendications de jeton, dans l’article Ajouter des attributs utilisateur aux revendications de jeton.
Déconnecter l’utilisateur
Pour déconnecter un utilisateur, utilisez la référence au MSALNativeAuthUserAccountResult
que vous avez reçu dans le rappel onSignInCompleted
, ou utilisez getNativeAuthUserAccount()
pour obtenir un compte connecté à partir du cache et stocker une référence dans la variable membre accountResult
.
Configurez le groupe de trousseaux pour votre projet, comme décrit ici.
Ajoutez une nouvelle variable membre à votre
ViewController
classe :var accountResult: MSALNativeAuthUserAccountResult?
.Mettez à jour
viewDidLoad
pour récupérer n’importe quel compte mis en cache en ajoutant cette ligne après quenativeAuth
soit initialisée correctement :accountResult = nativeAuth.getNativeAuthUserAccount()
.Mettez à jour le gestionnaire
signInCompleted
pour stocker le résultat du compte :func onSignInCompleted(result: MSALNativeAuthUserAccountResult) { resultTextView.text = "Signed in successfully" accountResult = result }
Ajoutez un bouton Déconnexion et utilisez le code suivant pour déconnecter l’utilisateur :
@IBAction func signOutPressed(_: Any) { guard let accountResult = accountResult else { print("Not currently signed in") return } accountResult.signOut() self.accountResult = nil resultTextView.text = "Signed out" }
Vous avez mené à bien toutes les étapes nécessaires pour déconnecter correctement un utilisateur sur votre application. Créez et exécutez votre application. Normalement, vous devriez pouvoir sélectionner le bouton de déconnexion et faire aboutir la déconnexion.
Configurer un fournisseur de revendications personnalisé
Si vous souhaitez ajouter des revendications à partir d’un système externe au jeton émis pour votre application, utilisez un fournisseur de revendications personnalisé. Un fournisseur de revendications personnalisé est constitué d’une extension d’authentification personnalisée qui appelle une API REST externe pour récupérer des revendications provenant de systèmes externes.
Suivez les étapes détaillées dans Configurer un fournisseur de revendications personnalisé pour ajouter des revendications à partir d’un système externe dans vos jetons de sécurité.