Tutoriel : appeler plusieurs API dans une application iOS/macOS en utilisant l’authentification native
S’applique à : iOS (Swift) macOS (Swift)
Dans ce tutoriel, vous allez apprendre à acquérir un jeton d’accès et à appeler une API dans votre application iOS/macOS. Le Kit de développement logiciel (SDK) d’authentification native de la bibliothèque d’authentification Microsoft (MSAL) pour iOS/macOS vous permet d’acquérir plusieurs jetons d’accès avec une authentification unique. Cette fonctionnalité vous permet d’acquérir un ou plusieurs jetons d’accès sans demander à un utilisateur de se réauthentifier.
Dans ce tutoriel, vous allez apprendre à :
- Acquérir un ou plusieurs jetons d’accès.
- Appeler une API
Prérequis
- Effectuez les étapes de l’article Connecter des utilisateurs et appeler une API dans un exemple d’application mobile iOS en utilisant l’authentification native.
- Effectuez les étapes du tutoriel : ajouter une fonctionnalité de connexion et de déconnexion dans l’application iOS/macOS en utilisant l’authentification native. Ce tutoriel vous montre comment connecter des utilisateurs dans votre application iOS/macOS en utilisant l’authentification native.
Acquérir un ou plusieurs jetons d’accès
Le Kit de développement logiciel (SDK) d’authentification native de MSAL peut stocker plusieurs jetons d’accès. Après vous être connecté, vous pouvez obtenir un jeton d’accès à l’aide de la fonction getAccessToken(scope:)
et spécifier les étendues du nouveau jeton d’accès que vous souhaitez accorder.
Déclarez et définissez des valeurs pour un ensemble d’étendues d’API à l’aide de l’extrait de code suivant :
let protectedAPIUrl1: String? = nil let protectedAPIUrl2: String? = nil let protectedAPIScopes1: [String] = [] let protectedAPIScopes2: [String] = [] var accessTokenAPI1: String? var accessTokenAPI2: String?
- Initialisez
protectedAPIUrl1
avec l’URL de votre première API web. - Initialisez
protectedAPIUrl2
avec l’URL de votre deuxième API web. - Définissez
protectedAPIScopes1
avec des étendues pour votre première API, par exemple["api://<Resource_App_ID>/ToDoList.Read", "api://<Resource_App_ID>/ToDoList.ReadWrite"]
. - Définissez
protectedAPIScopes2
avec des étendues pour votre deuxième API, similaire àprotectedAPIScopes1
. - Déclarez les variables de chaîne facultatives
accessTokenAPI1
etaccessTokenAPI2
.
- Initialisez
Connecte l’utilisateur à l’aide de l’extrait de code suivant :
@IBAction func signInPressed(_: Any) { guard let email = emailTextField.text, let password = passwordTextField.text else { resultTextView.text = "Email or password not set" return } print("Signing in with email \(email) and password") showResultText("Signing in...") nativeAuth.signIn(username: email, password: password, delegate: self) }
La méthode
signInPressed
gère l’appui sur le bouton de connexion. Elle vérifie si les champs d’e-mail et de mot de passe sont remplis. Si l’un ou l’autre est vide, elle affiche E-mail ou mot de passe non défini. Si les deux champs sont remplis, elle enregistre l’e-mail, affiche Connexion en cours... et lance la connexion à l’aide de la méthodesignIn
à partir denativeAuth
avec l’e-mail et le mot de passe fournis. Le Kit de développement logiciel (SDK) récupère un jeton valide pour les étendues OIDC par défaut (openid, offline_access, profile), car aucune étendue n’est spécifiée.Acquérir un ou plusieurs jetons d’accès à l’aide de l’extrait de code suivant :
@IBAction func protectedApi1Pressed(_: Any) { guard let url = protectedAPIUrl1, !protectedAPIScopes1.isEmpty else { showResultText("API 1 not configured.") return } if let accessToken = accessTokenAPI1 { accessProtectedAPI(apiUrl: url, accessToken: accessToken) } else { accountResult?.getAccessToken(scopes: protectedAPIScopes1, delegate: self) let message = "Retrieving access token to use with API 1..." showResultText(message) print(message) } } @IBAction func protectedApi2Pressed(_: Any) { guard let url = protectedAPIUrl2, !protectedAPIScopes2.isEmpty else { showResultText("API 2 not configured.") return } if let accessToken = accessTokenAPI2 { accessProtectedAPI(apiUrl: url, accessToken: accessToken) } else { accountResult?.getAccessToken(scopes: protectedAPIScopes2, delegate: self) let message = "Retrieving access token to use with API 2..." showResultText(message) print(message) } }
Les méthodes
protectedApi1Pressed
etprotectedApi2Pressed
gèrent le processus d’acquisition de jetons d’accès pour deux ensembles distincts d’étendues. Elles s’assurent d’abord que l’URL et les étendues de chaque API sont correctement configurées. Si un jeton d’accès pour l’API est déjà disponible, elle accède directement à l’API. Sinon, elle demande un jeton d’accès et informe l’utilisateur du processus de récupération de jeton en cours.Pour affecter un jeton d’accès à
protectedAPIScopes1
etprotectedAPIScopes2
, utilisez l’extrait suivant :func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) { print("Access Token: \(result.accessToken)") if protectedAPIScopes1.allSatisfy(result.scopes.contains), let url = protectedAPIUrl1 { accessTokenAPI1 = result.accessToken accessProtectedAPI(apiUrl: url, accessToken: result.accessToken) } if protectedAPIScopes2.allSatisfy(result.scopes.contains(_:)), let url = protectedAPIUrl2 { accessTokenAPI2 = result.accessToken accessProtectedAPI(apiUrl: url, accessToken: result.accessToken) } showResultText("Signed in." + "\n\n" + "Scopes:\n\(result.scopes)" + "\n\n" + "Access Token:\n\(result.accessToken)") updateUI() } func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) { showResultText("Error retrieving access token: \(error.errorDescription ?? "No error description")") }
La méthode
onAccessTokenRetrieveCompleted
affiche le jeton d’accès dans la console. Elle vérifie ensuite si desprotectedAPIScopes1
sont incluses dans les étendues du résultat et si uneprotectedAPIUrl1
est disponible. Si c’est le cas, elle définit l’accessTokenAPI1
et appelle l’accessProtectedAPI
avec l’URL et le jeton. Elle effectue une vérification similaire pourprotectedAPIScopes2
etprotectedAPIUrl2
en mettant à jour l’accessTokenAPI2
et en appelant l’API si les conditions sont remplies. Pour finir, la méthode affiche un message avec l’état de connexion, les étendues et le jeton d’accès, et met à jour l’interface utilisateur.La méthode
onAccessTokenRetrieveError
affiche un message d’erreur avec la description de l’erreur de récupération du jeton d’accès ou un message par défaut si aucune description n’est fournie.
Appeler une API
Utilisez les extraits de code suivants pour appeler une API :
func accessProtectedAPI(apiUrl: String, accessToken: String) {
guard let url = URL(string: apiUrl) else {
let errorMessage = "Invalid API url"
print(errorMessage)
DispatchQueue.main.async {
self.showResultText(errorMessage)
}
return
}
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error found when accessing API: \(error.localizedDescription)")
DispatchQueue.main.async {
self.showResultText(error.localizedDescription)
}
return
}
guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode)
else {
DispatchQueue.main.async {
self.showResultText("Unsuccessful response found when accessing the API")
}
return
}
guard let data = data, let result = try? JSONSerialization.jsonObject(with: data, options: []) else {
DispatchQueue.main.async {
self.showResultText("Couldn't deserialize result JSON")
}
return
}
DispatchQueue.main.async {
self.showResultText("""
Accessed API successfully using access token.
HTTP response code: \(httpResponse.statusCode)
HTTP response body: \(result)
""")
}
}
task.resume()
}
La méthode accessProtectedAPI
envoie une requête GET au point de terminaison d’API spécifié en utilisant le jeton d’accès fourni. Elle configure la requête avec le jeton dans l’en-tête d’autorisation. Lorsqu’elle reçoit une réponse de réussite (code d’état HTTP 200-299), elle désérialise les données JSON et met à jour l’interface utilisateur avec le code d’état HTTP et le corps de la réponse. Si une erreur se produit pendant la gestion de la requête ou de la réponse, elle affiche le message d’erreur dans l’interface utilisateur. Cette méthode permet d’accéder à l’API 1 ou à l’API 2, en fonction de l’URL et du jeton d’accès fournis.