Поделиться через


Руководство. Вызов нескольких API в приложении iOS с помощью собственной проверки подлинности

В этом руководстве вы узнаете, как получить маркер доступа и вызвать API в мобильном приложении iOS. Microsoft Authentication Library (MSAL) native authentication SDK для iOS позволяет получить несколько маркеров доступа с помощью единого входа. Эта возможность позволяет получить один или несколько маркеров доступа, не требуя повторной проверки подлинности пользователя.

В этом руководстве описано следующее:

  • Получение одного или нескольких маркеров доступа.
  • Вызов API

Необходимые компоненты

Получение одного или нескольких маркеров доступа

Пакет SDK для собственной проверки подлинности MSAL может хранить несколько маркеров доступа. После входа вы можете получить маркер доступа с помощью getAccessToken(scope:) функции и указать области для нового маркера доступа, который вы хотите предоставить.

  1. Объявите и задайте значения для набора областей API с помощью следующего фрагмента кода:

    let protectedAPIUrl1: String? = nil
    let protectedAPIUrl2: String? = nil 
    let protectedAPIScopes1: [String] = []
    let protectedAPIScopes2: [String] = []
    
    var accessTokenAPI1: String?
    var accessTokenAPI2: String?
    
    • Инициализация protectedAPIUrl1 с URL-адресом первого веб-API.
    • Инициализация protectedAPIUrl2 с URL-адресом второго веб-API.
    • Определите protectedAPIScopes1 области для первого API, например ["api://<Resource_App_ID>/ToDoList.Read", "api://<Resource_App_ID>/ToDoList.ReadWrite"].
    • Определите protectedAPIScopes2 области для второго API, аналогичное protectedAPIScopes1.
    • Объявите необязательные строковые переменные accessTokenAPI1 и accessTokenAPI2.
  2. Войдите в систему с помощью следующего фрагмента кода:

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

    Метод signInPressed обрабатывает нажатие кнопки входа. Он проверяет, заполнены ли поля электронной почты и пароля. Если значение пусто, отображается сообщение "Электронная почта или пароль не заданы". Если оба поля заполнены, он записывает сообщение электронной почты, отображает сообщение "Вход..." и инициирует вход с помощью signIn метода с nativeAuth предоставленным адресом электронной почты и пароля. Пакет SDK извлекает маркер, допустимый для областей OIDC по умолчанию (openid, offline_access, profile), так как области не указаны.

  3. Получите один или несколько маркеров доступа с помощью следующего фрагмента кода:

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

    protectedApi2Pressed Методы protectedApi1Pressed управляют процессом получения маркеров доступа для двух различных наборов областей. Сначала они гарантируют правильность настройки URL-адреса и областей каждого API. Если маркер доступа для API уже доступен, он напрямую обращается к API. В противном случае он запрашивает маркер доступа и сообщает пользователю о текущем процессе извлечения маркера.

    Чтобы назначить маркер protectedAPIScopes1 доступа и protectedAPIScopes2используйте следующий фрагмент кода:

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

    Метод onAccessTokenRetrieveCompleted выводит маркер доступа в консоль. Затем он проверяет, включены ли protectedAPIScopes1 они в области результатов и protectedAPIUrl1 если они доступны; если да, он задает accessTokenAPI1 и вызывает accessProtectedAPI URL-адрес и маркер. Он выполняет аналогичную проверку и protectedAPIScopes2 protectedAPIUrl2обновление accessTokenAPI2 и выполнение вызова API в случае выполнения условий. Наконец, метод отображает сообщение с состоянием входа, областями и маркером доступа и обновляет пользовательский интерфейс.

    Метод onAccessTokenRetrieveError отображает сообщение об ошибке с описанием ошибки извлечения маркера доступа или сообщения по умолчанию, если описание не указано.

Вызов API

Используйте следующие фрагменты кода для вызова 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()
}

Метод accessProtectedAPI отправляет запрос GET в указанную конечную точку API с помощью предоставленного маркера доступа. Он настраивает запрос с маркером в заголовке авторизации. Когда он получает успешный ответ (код состояния HTTP 200-299), он десериализирует данные JSON и обновляет пользовательский интерфейс с кодом состояния HTTP и текстом ответа. Если во время обработки запроса или ответа возникает ошибка, отображается сообщение об ошибке в пользовательском интерфейсе. Этот метод позволяет получить доступ к API 1 или API 2 в зависимости от URL-адреса и маркера доступа.