Udostępnij za pośrednictwem


Samouczek: wywoływanie wielu interfejsów API w aplikacji systemu iOS przy użyciu uwierzytelniania natywnego

Z tego samouczka dowiesz się, jak uzyskać token dostępu i wywołać interfejs API w aplikacji mobilnej systemu iOS. Natywny zestaw SDK uwierzytelniania biblioteki Microsoft Authentication Library (MSAL) dla systemu iOS umożliwia uzyskanie wielu tokenów dostępu przy użyciu logowania jednokrotnego. Ta funkcja umożliwia uzyskanie co najmniej jednego tokenu dostępu bez konieczności ponownego uwierzytelnienia użytkownika.

Z tego samouczka dowiesz się, jak wykonywać następujące czynności:

  • Uzyskaj jeden lub wiele tokenów dostępu.
  • Wywoływanie interfejsu API

Wymagania wstępne

Uzyskiwanie jednego lub wielu tokenów dostępu

Zestaw SDK uwierzytelniania natywnego biblioteki MSAL może przechowywać wiele tokenów dostępu. Po zalogowaniu można uzyskać token dostępu przy użyciu getAccessToken(scope:) funkcji i określić zakresy dla nowego tokenu dostępu, który chcesz udzielić.

  1. Zadeklaruj i ustaw wartości dla zestawu zakresów interfejsu API przy użyciu następującego fragmentu kodu:

    let protectedAPIUrl1: String? = nil
    let protectedAPIUrl2: String? = nil 
    let protectedAPIScopes1: [String] = []
    let protectedAPIScopes2: [String] = []
    
    var accessTokenAPI1: String?
    var accessTokenAPI2: String?
    
    • Zainicjuj protectedAPIUrl1 adres URL pierwszego internetowego interfejsu API.
    • Zainicjuj protectedAPIUrl2 adres URL drugiego internetowego interfejsu API.
    • Zdefiniuj protectedAPIScopes1 zakresy dla pierwszego interfejsu API, na przykład ["api://<Resource_App_ID>/ToDoList.Read", "api://<Resource_App_ID>/ToDoList.ReadWrite"].
    • Zdefiniuj protectedAPIScopes2 zakresy dla drugiego interfejsu API, podobnie jak protectedAPIScopes1.
    • Zadeklaruj opcjonalne zmienne accessTokenAPI1 ciągu i accessTokenAPI2.
  2. Loguje użytkownika przy użyciu następującego fragmentu kodu:

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

    Metoda signInPressed obsługuje naciśnięcie przycisku logowania. Sprawdza, czy pola wiadomości e-mail i hasła są wypełnione. Jeśli wartość jest pusta, zostanie wyświetlony komunikat "Adres e-mail lub hasło nie jest ustawione". Jeśli oba pola są wypełnione, rejestruje wiadomość e-mail, wyświetla komunikat "Logowanie..." i inicjuje logowanie przy użyciu signIn metody z nativeAuth podanej wiadomości e-mail i hasła. Zestaw SDK pobiera token prawidłowy dla domyślnych zakresów OIDC (openid, offline_access, profile), ponieważ nie określono zakresów.

  3. Uzyskaj jeden lub wiele tokenów dostępu przy użyciu następującego fragmentu kodu:

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

    Metody protectedApi1Pressed i protectedApi2Pressed zarządzają procesem uzyskiwania tokenów dostępu dla dwóch odrębnych zestawów zakresów. Najpierw upewniają się, że adres URL i zakresy poszczególnych interfejsów API są prawidłowo skonfigurowane. Jeśli token dostępu dla interfejsu API jest już dostępny, uzyskuje bezpośredni dostęp do interfejsu API. W przeciwnym razie żąda tokenu dostępu i informuje użytkownika o trwającym procesie pobierania tokenu.

    Aby przypisać token dostępu do protectedAPIScopes1 elementów i protectedAPIScopes2, użyj następującego fragmentu kodu:

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

    Metoda onAccessTokenRetrieveCompleted wyświetla token dostępu do konsoli. Następnie sprawdza, czy protectedAPIScopes1 są uwzględnione w zakresach wyniku i czy protectedAPIUrl1 są dostępne. Jeśli tak, ustawia accessTokenAPI1 i wywołuje accessProtectedAPI adres URL i token. Wykonuje on podobne sprawdzanie protectedAPIScopes2 parametrów i protectedAPIUrl2, aktualizując accessTokenAPI2 i wykonując wywołanie interfejsu API w przypadku spełnienia warunków. Na koniec metoda wyświetla komunikat ze stanem logowania, zakresami i tokenem dostępu oraz aktualizuje interfejs użytkownika.

    Metoda onAccessTokenRetrieveError wyświetla komunikat o błędzie z opisem błędu pobierania tokenu dostępu lub komunikatem domyślnym, jeśli nie podano opisu.

Wywoływanie interfejsu API

Użyj następujących fragmentów kodu, aby wywołać interfejs 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()
}

Metoda accessProtectedAPI wysyła żądanie GET do określonego punktu końcowego interfejsu API przy użyciu podanego tokenu dostępu. Konfiguruje żądanie za pomocą tokenu w nagłówku Autoryzacja. Po otrzymaniu pomyślnej odpowiedzi (kod stanu HTTP 200–299) deserializuje dane JSON i aktualizuje interfejs użytkownika przy użyciu kodu stanu HTTP i treści odpowiedzi. Jeśli podczas obsługi żądania lub odpowiedzi wystąpi błąd, zostanie wyświetlony komunikat o błędzie w interfejsie użytkownika. Ta metoda umożliwia dostęp do interfejsu API 1 lub API 2 w zależności od podanego adresu URL i tokenu dostępu.