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


Руководство. Добавление входа и выхода в приложение iOS/macOS с помощью собственной проверки подлинности

Область применения: Зеленый круг с символом белой галочки. iOS (Swift) Зеленый круг с символом белой галочки. macOS (Swift) (Swift)

В этом руководстве показано, как войти и выйти пользователя с помощью однократного секретного кода или пароля электронной почты в приложении iOS/macOS с помощью собственной проверки подлинности.

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

  • Войдите в систему, используя одноразовый секретный код электронной почты или имя пользователя (электронная почта) и пароль.
  • Выйдите из пользователя.
  • Обработка ошибки входа

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

Вход пользователя

Чтобы войти в систему пользователя с помощью потока однократного секретного кода электронной почты, запишите сообщение электронной почты и отправьте сообщение электронной почты, содержащее одноразовый секретный код для пользователя, чтобы проверить свой адрес электронной почты. Когда пользователь вводит действительный одноразовый секретный код, приложение войдет в систему.

Чтобы войти в систему пользователя с помощью потока паролей , запишите сообщение электронной почты и пароль. Если имя пользователя и пароль действительны, приложение войдите в систему пользователя.

Чтобы войти в систему, необходимо выполнить следующие действия.

  1. Создайте пользовательский интерфейс для:

    • Сбор сообщения электронной почты от пользователя. Добавьте проверку в входные данные, чтобы убедиться, что пользователь вводит допустимый адрес электронной почты.
    • Соберите пароль при входе с помощью имени пользователя (электронной почты) и пароля.
    • Соберите одноразовый секретный код электронной почты от пользователя, если вы войдите в систему с помощью однократного секретного кода электронной почты.
    • Добавьте кнопку, чтобы разрешить пользователю повторно отправить одноразовый секретный код при входе с помощью однократного секретного кода электронной почты.
  2. В пользовательском интерфейсе добавьте кнопку, событие выбора которой запускает вход, как показано в следующем фрагменте кода:

        @IBAction func signInPressed(_: Any) {
        guard let email = emailTextField.text else {
            resultTextView.text = "email not set"
            return
        }
    
        nativeAuth.signIn(username: email, delegate: self)
    }
    

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

    nativeAuth.signIn(username: email, delegate: self)
    

    Метод signIn(username:delegate) , который отвечает асинхронно путем вызова одного из методов в переданном объекте делегата, должен реализовать SignInStartDelegate протокол. Передайте адрес электронной почты, который пользователь предоставляет в форме отправки электронной почты и передается self в качестве делегата.

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

    nativeAuth.signIn(username: email, password: password, delegate: self)
    

    В методе signIn(username:password:delegate) вы передаете адрес электронной почты, предоставленный пользователем, своим паролем, и передаете объект делегата, соответствующий протоколу SignInStartDelegate . В этом примере мы передаем self.

  3. Чтобы реализовать SignInStartDelegate протокол при использовании потока одноразового секретного кода электронной почты, используйте следующий фрагмент кода:

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCodeRequired(
            newState: MSAL.SignInCodeRequiredState,
            sentTo: String,
            channelTargetType: MSAL.MSALNativeAuthChannelType,
            codeLength: Int
        ) {
            resultTextView.text = "Verification code sent to \(sentTo)"
        }
    }
    

    signIn(username:delegate) Результаты вызова методов делегирования. В наиболее распространенном сценарии onSignInCodeRequired(newState:sentTo:channelTargetType:codeLength) вызывается, чтобы указать, что код отправлен для проверки адреса электронной почты пользователя. Наряду с некоторыми сведениями о том, где был отправлен код, и сколько цифр он содержит, этот метод делегата также имеет newState параметр типа SignInCodeRequiredState, который предоставляет нам доступ к следующим двум новым методам:

    • submitCode(code:delegate)
    • resendCode(delegate)

    Используйте submitCode(code:delegate) для отправки одноразового секретного кода, который пользователь предоставляет в форме одноразового секретного кода, используйте следующий фрагмент кода:

    newState.submitCode(code: userSuppliedCode, delegate: self)
    

    Принимает submitCode(code:delegate) одноразовый секретный код и параметр делегата. После отправки кода необходимо проверить одноразовый секретный код, реализуя SignInVerifyCodeDelegate протокол.

    Чтобы реализовать SignInVerifyCodeDelegate протокол в качестве расширения для класса, используйте следующий фрагмент кода:

    extension ViewController: SignInVerifyCodeDelegate {
        func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
            resultTextView.text = "Signed in successfully."
            result.getAccessToken(delegate: self)
        }
    }
    

    В наиболее распространенном сценарии мы получаем вызов, указывающий onSignInCompleted(result) , что пользователь вошел в систему. Результат можно использовать для извлечения access token.

    Принимает getAccessToken(delegate) параметр делегата, и мы должны реализовать необходимые методы в протоколе CredentialsDelegate .

    В наиболее распространенном сценарии мы получаем вызов, onAccessTokenRetrieveCompleted(result) указывающий, что пользователь получил .access token

    extension ViewController: CredentialsDelegate {
        func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) {
            resultTextView.text = "Error retrieving access token"
        }
    
        func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) {
            resultTextView.text = "Signed in. Access Token: \(result.accessToken)"
        }
    }
    
    
  4. Чтобы реализовать SignInStartDelegate протокол при использовании электронной почты с потоком паролей , используйте следующий фрагмент кода:

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
            // User successfully signed in
        }
    }
    

    В наиболее распространенном сценарии мы получаем вызов, указывающий onSignInCompleted(result) , что пользователь вошел в систему. Результат можно использовать для извлечения access token.

    Принимает getAccessToken(delegate) параметр делегата, и мы должны реализовать необходимые методы в протоколе CredentialsDelegate .

    В наиболее распространенном сценарии мы получаем вызов, onAccessTokenRetrieveCompleted(result) указывающий, что пользователь получил .access token

    extension ViewController: CredentialsDelegate {
        func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) {
            resultTextView.text = "Error retrieving access token"
        }
    
        func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) {
            resultTextView.text = "Signed in. Access Token: \(result.accessToken)"
        }
    }
    
    

Обработка ошибок входа

Во время входа не все действия успешно выполнены. Например, пользователь может попытаться войти с помощью адреса электронной почты, который не существует, или отправить недопустимый код.

  1. Для обработки ошибок в или signIn(username, password) методе signIn(username) используйте следующий фрагмент кода:

    func onSignInStartError(error: MSAL.SignInStartError) {
        if error.isUserNotFound || error.isInvalidUsername {
            resultTextView.text = "Invalid username"
        } else {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    }
    
  2. Для обработки ошибок в submitCode() методе используйте следующий фрагмент кода:

    func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
        if error.isInvalidCode {
            // Inform the user that the submitted code was incorrect and ask for a new code to be supplied
            let userSuppliedCode = retrieveNewCode()
            newState?.submitCode(code: userSuppliedCode, delegate: self)
        } else {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    }
    

    Если пользователь вводит неверный код проверки электронной почты, обработчик ошибок содержит ссылку на объект SignInCodeRequiredState , который можно использовать для отправки обновленного кода. В более ранней SignInVerifyCodeDelegate реализации протокола мы просто отображали ошибку при обработке функции делегата onSignInVerifyCodeError(error:newState) .

Чтение утверждений маркера идентификатора

После получения маркера идентификатора приложение сможет получить утверждения, связанные с текущей учетной записью. Для этого используйте следующий фрагмент кода:

func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
   let claims = result.account.accountClaims
   let preferredUsername = claims?["preferred_username"] as? String
}

Ключ, используемый для доступа к значению утверждения, — это имя, указанное при добавлении атрибута пользователя в качестве утверждения токена.

Узнайте, как добавить встроенные и пользовательские атрибуты в качестве утверждений токена в статье "Добавление атрибутов пользователя" в статью о утверждениях токенов.

Выход пользователя

Чтобы выйти пользователя, используйте ссылку на MSALNativeAuthUserAccountResult полученную в onSignInCompleted обратном вызове учетную запись или используйте getNativeAuthUserAccount() для получения любой учетной записи входа из кэша и сохранения ссылки в переменной-члене accountResult .

  1. Настройте группу цепочки ключей для проекта, как описано здесь.

  2. Добавьте новую переменную-член в ViewController класс: var accountResult: MSALNativeAuthUserAccountResult?

  3. ОбновитеviewDidLoad, чтобы получить любую кэшированную учетную запись, добавив эту строку после nativeAuth успешной инициализации: accountResult = nativeAuth.getNativeAuthUserAccount()

  4. Обновите обработчик, чтобы сохранить результат учетной signInCompleted записи:

    func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
        resultTextView.text = "Signed in successfully"
    
        accountResult = result
    }
    
  5. Добавьте кнопку выхода и используйте следующий код для выхода пользователя:

    @IBAction func signOutPressed(_: Any) {
        guard let accountResult = accountResult else {
            print("Not currently signed in")
            return
        }
    
        accountResult.signOut()
    
        self.accountResult = nil
    
        resultTextView.text = "Signed out"
    }
    

Вы успешно выполнили все необходимые действия для выхода пользователя в приложение. Скомпилируйте и запустите приложение. Если все хорошо, вы сможете выбрать кнопку выхода, чтобы успешно выйти.

Настройка настраиваемого поставщика утверждений

Если вы хотите добавить утверждения из внешней системы в маркер, выданный приложению, используйте настраиваемый поставщик утверждений. Настраиваемый поставщик утверждений состоит из настраиваемого расширения проверки подлинности, вызывающего внешний REST API для получения утверждений из внешних систем.

Выполните действия, описанные в разделе "Настройка настраиваемого поставщика утверждений" для добавления утверждений из внешней системы в маркеры безопасности.