Dela via


Självstudie: Anropa flera API:er i iOS-appen med inbyggd autentisering

I den här självstudien får du lära dig hur du skaffar en åtkomsttoken och anropar ett API i din iOS-mobilapp. Med Microsoft Authentication Library (MSAL) intern autentiserings-SDK för iOS kan du hämta flera åtkomsttoken med enkel inloggning. Med den här funktionen kan du hämta en eller flera åtkomsttoken utan att kräva att en användare autentiserar igen.

I den här självstudien lär du dig att:

  • Hämta en eller flera åtkomsttoken.
  • Anropa ett API

Förutsättningar

Hämta en eller flera åtkomsttoken

MSAL native authentication SDK kan lagra flera åtkomsttoken. När du har loggat in kan du hämta en åtkomsttoken med hjälp getAccessToken(scope:) av funktionen och ange omfången för den nya åtkomsttoken som du vill bevilja.

  1. Deklarera och ange värden för en uppsättning API-omfång med hjälp av följande kodfragment:

    let protectedAPIUrl1: String? = nil
    let protectedAPIUrl2: String? = nil 
    let protectedAPIScopes1: [String] = []
    let protectedAPIScopes2: [String] = []
    
    var accessTokenAPI1: String?
    var accessTokenAPI2: String?
    
    • protectedAPIUrl1 Initiera med URL:en för ditt första webb-API.
    • protectedAPIUrl2 Initiera med URL:en för ditt andra webb-API.
    • Definiera protectedAPIScopes1 med omfång för ditt första API, till exempel ["api://<Resource_App_ID>/ToDoList.Read", "api://<Resource_App_ID>/ToDoList.ReadWrite"].
    • Definiera protectedAPIScopes2 med omfång för ditt andra API, ungefär som protectedAPIScopes1.
    • Deklarera de valfria strängvariablerna accessTokenAPI1 och accessTokenAPI2.
  2. Loggar in användaren med hjälp av följande kodfragment:

    @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)
    }
    

    Metoden signInPressed hanterar inloggningsknappen. Den kontrollerar om e-post- och lösenordsfälten är ifyllda. Om någon av dem är tom visas "E-post eller lösenord har inte angetts". Om båda fälten är ifyllda loggar den e-postmeddelandet, visar "Logga in..." och initierar inloggningen signIn med hjälp av metoden från nativeAuth med det angivna e-postmeddelandet och lösenordet. SDK:n hämtar en token som är giltig för OIDC-standardomfången (openid, offline_access, profil) eftersom inga omfång har angetts.

  3. Hämta en eller flera åtkomsttoken med hjälp av följande kodfragment:

    @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)
        }
    }
    

    Metoderna protectedApi1Pressed och protectedApi2Pressed hanterar processen för att hämta åtkomsttoken för två distinkta uppsättningar med omfång. De ser först till att varje API:s URL och omfång är korrekt konfigurerade. Om en åtkomsttoken för API:et redan är tillgänglig kommer den direkt åt API:et. Annars begär den en åtkomsttoken och informerar användaren om den pågående tokenhämtningsprocessen.

    Om du vill tilldela en åtkomsttoken till protectedAPIScopes1 och protectedAPIScopes2använder du följande kodfragment:

    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")")
    }
    

    Metoden onAccessTokenRetrieveCompleted skriver ut åtkomsttoken till konsolen. Den kontrollerar sedan om protectedAPIScopes1 ingår i resultatets omfång och om protectedAPIUrl1 det är tillgängligt. I så fall anges accessTokenAPI1 och anropas accessProtectedAPI det med URL:en och token. Den utför en liknande kontroll för protectedAPIScopes2 och protectedAPIUrl2, uppdaterar accessTokenAPI2 och gör API-anropet om villkoren uppfylls. Slutligen visar metoden ett meddelande med inloggningsstatus, omfång och åtkomsttoken och uppdaterar användargränssnittet.

    Metoden onAccessTokenRetrieveError visar ett felmeddelande med beskrivningen av hämtningsfelet för åtkomsttoken eller ett standardmeddelande om ingen beskrivning anges.

Anropa ett API

Använd följande kodfragment för att anropa ett 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()
}

Metoden accessProtectedAPI skickar en GET-begäran till den angivna API-slutpunkten med hjälp av den angivna åtkomsttoken. Den konfigurerar begäran med token i auktoriseringshuvudet. När det får ett lyckat svar (HTTP-statuskod 200-299) deserialiserar det JSON-data och uppdaterar användargränssnittet med HTTP-statuskoden och svarstexten. Om ett fel uppstår under hanteringen av begäran eller svar visas felmeddelandet i användargränssnittet. Den här metoden ger åtkomst till antingen API 1 eller API 2, beroende på vilken URL och åtkomsttoken som tillhandahålls.