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


Включение аутентификацию в вашем приложении Swift для iOS с помощью Azure AD B2C

В этой статье показано, как добавить аутентификацию Azure Active Directory B2C (Azure AD B2C) в собственное мобильное приложение Swift для iOS. Узнайте, как интегрировать приложение Swift для iOS с Библиотекой аутентификации Майкрософт (MSAL) для iOS.

Используйте эту статью вместе с настройкой аутентификации в примере приложения Swift для iOS, заменив приложение Swift для iOS из примера своим собственным приложением Swift для iOS. После выполнения инструкций, описанных в этой статье, ваше приложение будет принимать запросы на вход через Azure AD B2C.

Предварительные требования

Ознакомьтесь с предварительными требованиями и инструкциями по интеграции в разделе Настройка проверки подлинности в образце приложения Swift для iOS с помощью Azure AD B2C.

Создание проекта приложения Swift для iOS

Если у вас еще нет приложения iOS Swift, настройте новый проект, выполнив следующие действия.

  1. Откройте Xcode и выберите Файл>Новый>Проект.
  2. Для приложений iOS выберите iOS>Приложение, а затем выберите Далее.
  3. В разделе Выбор параметров нового проекта укажите следующее:
    1. Название продукта, например MSALiOS.
    2. Идентификатор организации, например contoso.com.
    3. В качестве значения параметра Интерфейс выберите Раскадровка.
    4. В качестве значения параметра Жизненный цикл выберите Делегат приложения UIKit.
    5. В качестве значения параметра Язык выберите Swift.
  4. Выберите Далее.
  5. Выберите папку, в которой будет создано приложение, и нажмите Создать.

Шаг 1. Установка библиотеки MSAL

  1. Для установки библиотеки MSAL используйте CocoaPods. В той же папке, что и XCODEPROJ-файл проекта, если файл podfile не существует, создайте пустой файл и присвойте ему имя podfile. Добавьте в файл podfile следующий код:

    use_frameworks!
    
    target '<your-target-here>' do
       pod 'MSAL'
    end
    
  2. Замените <your-target-here> на имя вашего проекта (например, MSALiOS). Дополнительные сведения см. в справке по синтаксису Podfile.

  3. В окне терминала перейдите в папку, где находится файл podfile, и запустите pod install, чтобы установить библиотеку MSAL.

  4. После запуска команды pod install будет создан файл <имя вашего проекта>.xcworkspace. Чтобы перезагрузить проект в Xcode, закройте Xcode и откройте файл <имя вашего проекта>.xcworkspace.

Шаг 2. Настройка схемы URL-адресов приложения

Когда пользователь аутентифицируется, Azure AD B2C отправляет в приложение код авторизации с помощью универсального кода ресурса (URI) перенаправления, настроенного при регистрации приложения Azure AD B2C.

Формат URI перенаправления MSAL по умолчанию — msauth.[Your_Bundle_Id]://auth. Например, это может быть msauth.com.microsoft.identitysample.MSALiOS://auth, где msauth.com.microsoft.identitysample.MSALiOS — схема URL-адресов.

На этом шаге зарегистрируйте вашу схему URL-адресов с помощью массива CFBundleURLSchemes. Приложение прослушивает схему URL-адресов для обратного вызова из Azure AD B2C.

В Xcode откройте файл Info.plist в качестве файла исходного кода. В разделе <dict> добавьте следующий фрагмент кода XML:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>msauth.com.microsoft.identitysample.MSALiOS</string>
        </array>
    </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>msauthv2</string>
    <string>msauthv3</string>
</array>

Шаг 3. Добавление кода проверки подлинности

Пример кода создан на основе класса UIViewController. Класс:

  • Определяет структуру пользовательского интерфейса.
  • Содержит сведения о поставщике удостоверений Azure AD B2C. Приложение использует эти сведения для установления отношений доверия с Azure AD B2C.
  • Содержит код проверки подлинности для проверки подлинности пользователей, получает маркеры проверки подлинности и проверяет их.

Выберите, где UIViewController пользователи проходят проверку подлинности. В UIViewController объедините код с кодом, предоставленным в GitHub.

Шаг 4. Настройка вашего приложения Swift для iOS

Добавив код проверки подлинности, настройте приложение Swift для iOS с помощью параметров Azure AD B2C. Параметры поставщика удостоверений Azure AD B2C настраиваются в классе UIViewController, выбранном в предыдущем разделе.

Чтобы узнать, как настроить приложение Swift для iOS, см. статью Настройка проверки подлинности в образце приложения iOS с помощью Azure AD B2C.

Шаг 5. Запуск и тестирование мобильного приложения

  1. Создайте и запустите проект с помощью симулятора подключенного устройства iOS.
  2. Выберите Войти, затем зарегистрируйтесь или войдите в систему с помощью локальной учетной записи Azure AD B2C или учетной записи социальной сети.
  3. После успешной аутентификации на панели навигации появится ваше отображаемое имя.

Шаг 6. Настройка составляющих блоков кода

В этом разделе описаны составляющие блоки кода, которые обеспечивают аутентификацию для приложения Swift для iOS. В нем перечислены методы UIViewController и описаны способы настройки кода.

Шаг 6.1. Создание экземпляра общедоступного клиентского приложения

Общедоступные клиентские приложения не считаются безопасными для хранения секретов приложения и не содержат секреты клиента. В viewDidLoad создайте экземпляр MSAL с помощью объекта клиентского приложения.

В следующем фрагменте кода Swift показано, как инициализировать MSAL с помощью объекта конфигурации MSALPublicClientApplicationConfig.

Объект конфигурации содержит информацию о среде Azure AD B2C. Например, он предоставляет идентификатор клиента, URI перенаправления и полномочия для создания запросов проверки подлинности для Azure AD B2C. Сведения об объекте конфигурации см. в статье Настройка примера мобильного приложения.

do {

    let signinPolicyAuthority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
    let editProfileAuthority = try self.getAuthority(forPolicy: self.kEditProfilePolicy)
    
    let pcaConfig = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: kRedirectUri, authority: signinPolicyAuthority)
    pcaConfig.knownAuthorities = [signinPolicyAuthority, editProfileAuthority]
    
    self.applicationContext = try MSALPublicClientApplication(configuration: pcaConfig)
    self.initWebViewParams()
    
    } catch {
        self.updateLoggingText(text: "Unable to create application \(error)")
    }

Метод initWebViewParams настраивает интерактивную проверку подлинности.

Следующий фрагмент кода Swift инициализирует член класса webViewParameters с системным веб-представлением. Более подробную информацию см. в статье Настройка браузеров и веб-представлений для iOS/macOS.

func initWebViewParams() {
    self.webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
    self.webViewParameters?.webviewType = .default
}

Шаг 6.2. Запуск интерактивного запроса на авторизацию

Интерактивный запрос авторизации — это поток, в котором пользователю предлагается зарегистрироваться или войти в систему с помощью системного веб-представления. Когда пользователи нажимают кнопку Войти, вызывается метод authorizationButton.

Метод authorizationButton подготавливает объект MSALInteractiveTokenParameters с использованием соответствующих данных о запросе авторизации. Метод acquireToken использует MSALInteractiveTokenParameters для проверки подлинности пользователей через системное веб-представление.

Следующий фрагмент кода показывает, как запустить интерактивный запрос авторизации.

let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: self.webViewParameters!)
parameters.promptType = .selectAccount
parameters.authority = authority

applicationContext.acquireToken(with: parameters) { (result, error) in

// On error code    
guard let result = result else {
    self.updateLoggingText(text: "Could not acquire token: \(error ?? "No error information" as! Error)")
    return
}

// On success code
self.accessToken = result.accessToken
self.updateLoggingText(text: "Access token is \(self.accessToken ?? "Empty")")
}

После того как пользователи завершат процесс авторизации (успешно или безуспешно), результат возвращается в замыкание метода acquireToken.

Метод acquireToken возвращает объекты result и error. Используйте это замыкание для выполнения следующих действий:

  • обновление пользовательского интерфейса мобильного приложения путем указания сведений после завершения проверки подлинности;
  • вызов службы веб-API с помощью маркера доступа;
  • обработка ошибок аутентификации, например, когда пользователь отменяет поток входа.

Шаг 6.3. Вызов службы веб-API

Для вызова веб-API авторизации на основе токена приложению требуется действительный маркер доступа. Приложение выполняет следующие действия:

  1. получает маркер доступа с необходимыми разрешениями (областями) для конечной точки веб-API;
  2. Передает маркер доступа как токен носителя в заголовке авторизации HTTP-запроса, используя следующий формат:
Authorization: Bearer <access-token>

Когда пользователи проходят интерактивную авторизацию, приложение получает маркер доступа в замыкании acquireToken. Для последующих вызовов веб-API, используйте тихий запрос токена с помощью метода acquireTokenSilent, как описано в этом разделе.

Метод acquireTokenSilent выполняет следующие действия:

  1. Пытается получить маркер доступа с запрошенными областями из кэша токенов. Токен возвращается, если он присутствует и срок его действия не истек.
  2. Если токен отсутствует в кэше токенов или срок его действия истек, библиотека MSAL пытается использовать маркер обновления для получения нового маркера доступа.
  3. Если маркер обновления не существует или срок его действия истек, возвращается исключение. В этом случае следует предложить пользователю выполнить интерактивный вход.

В следующем фрагменте кода показано, как получить маркер доступа:

do {

// Get the authority using the sign-in or sign-up user flow
let authority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)

// Get the current account from the application context
guard let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy) else {
    self.updateLoggingText(text: "There is no account available!")
    return
}

// Configure the acquire token silent parameters
let parameters = MSALSilentTokenParameters(scopes: kScopes, account:thisAccount)
parameters.authority = authority
parameters.loginHint = "username"

// Acquire token silent
self.applicationContext.acquireTokenSilent(with: parameters) { (result, error) in
    if let error = error {
        
        let nsError = error as NSError
        
        // interactionRequired means we need to ask the user to sign in. This usually happens
        // when the user's Refresh Token is expired or if the user has changed their password
        // among other possible reasons.
        
        if (nsError.domain == MSALErrorDomain) {
            
            if (nsError.code == MSALError.interactionRequired.rawValue) {
                
                // Start an interactive authorization code
                // Notice we supply the account here. This ensures we acquire token for the same account
                // as we originally authenticated.
                
                ...
            }
        }
        
        self.updateLoggingText(text: "Could not acquire token: \(error)")
        return
    }
    
    guard let result = result else {
        
        self.updateLoggingText(text: "Could not acquire token: No result returned")
        return
    }
    
    // On success, set the access token to the accessToken class member. 
    // The callGraphAPI method uses the access token to call a web API  
    self.accessToken = result.accessToken
    ...
}
} catch {
self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
}

Метод callGraphAPI получает маркер доступа и вызывает веб-API, как показано ниже:

@objc func callGraphAPI(_ sender: UIButton) {
    guard let accessToken = self.accessToken else {
        self.updateLoggingText(text: "Operation failed because could not find an access token!")
        return
    }
    
    let sessionConfig = URLSessionConfiguration.default
    sessionConfig.timeoutIntervalForRequest = 30
    let url = URL(string: self.kGraphURI)
    var request = URLRequest(url: url!)
    request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
    let urlSession = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
    
    self.updateLoggingText(text: "Calling the API....")
    
    urlSession.dataTask(with: request) { data, response, error in
        guard let validData = data else {
            self.updateLoggingText(text: "Could not call API: \(error ?? "No error information" as! Error)")
            return
        }
        
        let result = try? JSONSerialization.jsonObject(with: validData, options: [])
        
        guard let validResult = result as? [String: Any] else {
            self.updateLoggingText(text: "Nothing returned from API")
            return
        }
        
        self.updateLoggingText(text: "API response: \(validResult.debugDescription)")
        }.resume()
}

Шаг 6.4. Выход пользователей

При выходе из MSAL вся известная информация о пользователе будет удалена из приложения. Используйте метод выхода для выхода пользователей и обновления пользовательского интерфейса. Например, можно скрыть защищенные элементы пользовательского интерфейса, скрыть кнопку выхода или отобразить кнопку входа.

В следующем фрагменте кода показано, как выполнить выход пользователей:

@objc func signoutButton(_ sender: UIButton) {
do {
    
    
    let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy)
    
    if let accountToRemove = thisAccount {
        try applicationContext.remove(accountToRemove)
    } else {
        self.updateLoggingText(text: "There is no account to signing out!")
    }
    
    ...
    
} catch  {
    self.updateLoggingText(text: "Received error signing out: \(error)")
}
}

Дальнейшие действия

Вы узнаете, как выполнять следующие задачи: