Tutorial: adicionar o recurso de entrar e sair no aplicativo iOS/macOS usando autenticação nativa.
Aplica-se a: iOS (Swift)
macOS (Swift)
Esse tutorial demonstra como realizar a entrada e saída de um usuário usando uma senha de uso único por email ou um nome de usuário e senha no seu aplicativo iOS/macOS usando autenticação nativa.
Neste tutorial, você aprenderá a:
- Conecte um usuário usando senha única por email ou nome de usuário (email) e senha.
- Desconecte um usuário.
- Como lidar com erros de entrada
Pré-requisitos
- Tutorial: preparar seu aplicativo iOS/macOS para a autenticação nativa.
- Se quiser entrar usando o Email com senha, configure seu fluxo de usuário para usar Email com senha quando criar seu fluxo de entrada e saída de usuário.
Conectar usuário
Para conectar um usuário com o fluxo de senha de uso único por email, capture o email e envie um email contendo uma senha de uso único para o usuário verificar o respectivo email. Quando o usuário insere uma senha de uso único válida, o aplicativo o conecta.
Para que um usuário entre usando o fluxo de Email com senha, capture o email e a senha. Se o nome de usuário e a senha forem válidos, o aplicativo conectará o usuário.
Para conectar um usuário, você precisa:
Criar uma IU (interface do usuário) para:
- Coletar um email do usuário. Adicionar validação à interface do usuário para garantir que o usuário insira um endereço de email válido.
- Colete uma senha se você entrar com o nome de usuário (email) e a senha.
- Colete uma senha de uso único por email do usuário se você usar a senha de uso único por email para entrada.
- Se você entrar com a senha única por email, adicione um botão para permitir que o usuário reenvie a senha única.
Na interface do usuário, adicione um botão, cujo evento de seleção inicia uma entrada, conforme mostrado no seguinte trecho de código:
@IBAction func signInPressed(_: Any) { guard let email = emailTextField.text else { resultTextView.text = "email not set" return } let parameters = MSALNativeAuthSignInParameters(username: email) nativeAuth.signIn(parameters: parameters, delegate: self) }
Para que um usuário entre usando o fluxo de Senha única por email, usamos o seguinte snippet de código:
nativeAuth.signIn(parameters: parameters, delegate: self)
O método
signIn(parameters:delegate)
, que responde de maneira assíncrona chamando um dos métodos no objeto delegado repassado, precisa implementar o protocoloSignInStartDelegate
. Transmitimos uma instância deMSALNativeAuthSignInParameters
que contém o endereço de email que o usuário fornece no formulário de envio de email e transmitimosself
como o delegado.Para que um usuário entre usando o fluxo de Email com senha, usamos o seguinte snippet de código:
let parameters = MSALNativeAuthSignInParameters(username: email) parameters.password = password nativeAuth.signIn(parameters: parameters, delegate: self)
No método
signIn(parameters:delegate)
, você passa uma instância deMSALNativeAuthSignInParameters
que contém o endereço de email que o usuário nos forneceu e sua senha, juntamente com o objeto delegado que está em conformidade com o protocoloSignInStartDelegate
. Para esse exemplo, vamos repassarself
.Para implementar o protocolo
SignInStartDelegate
quando você usar o fluxo de Senha única por email, use o seguinte snippet de código: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)" } }
O
signIn(parameters:delegate)
resulta em uma chamada para delegação dos métodos. No cenário mais comum,onSignInCodeRequired(newState:sentTo:channelTargetType:codeLength)
é chamado para indicar que um código foi enviado para verificar o endereço de email do usuário. Acompanhado de alguns detalhes, como local de envio do código e número de dígitos que ele contém, esse método delegado também tem um parâmetronewState
do tipoSignInCodeRequiredState
, que nos dá acesso aos dois novos seguintes métodos:submitCode(code:delegate)
resendCode(delegate)
Para usar
submitCode(code:delegate)
ao enviar a senha de uso único que o usuário fornecer no formulário de senha de uso único, use o seguinte trecho de código:newState.submitCode(code: userSuppliedCode, delegate: self)
O
submitCode(code:delegate)
aceita a senha de uso único e o parâmetro delegado. Depois de enviar o código, você precisa verificar a senha de uso único implementando o protocoloSignInVerifyCodeDelegate
.Para implementar o protocolo
SignInVerifyCodeDelegate
como uma extensão da classe, use o seguinte snippet de código: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." let parameters = MSALNativeAuthGetAccessTokenParameters() result.getAccessToken(parameters: parameters, delegate: self) } }
No cenário mais comum, recebemos uma chamada a
onSignInCompleted(result)
, indicando que o usuário se conectou. O resultado pode ser usado para recuperar oaccess token
.O
getAccessToken(parameters:delegate)
aceita uma instânciaMSALNativeAuthGetAccessTokenParameters
e um parâmetro delegado e devemos implementar os métodos necessários no protocoloCredentialsDelegate
.No cenário mais comum, recebemos uma chamada a
onAccessTokenRetrieveCompleted(result)
, indicando que o usuário obteve umaccess 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)" } }
Para implementar o protocolo
SignInStartDelegate
quando você usar o fluxo de Email com senha, use o seguinte snippet de código: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 } }
No cenário mais comum, recebemos uma chamada a
onSignInCompleted(result)
, indicando que o usuário se conectou. O resultado pode ser usado para recuperar oaccess token
.O
getAccessToken(parameters:delegate)
aceita uma instânciaMSALNativeAuthGetAccessTokenParameters
e um parâmetro delegado e devemos implementar os métodos necessários no protocoloCredentialsDelegate
.No cenário mais comum, recebemos uma chamada a
onAccessTokenRetrieveCompleted(result)
, indicando que o usuário obteve umaccess 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)" } }
Como lidar com erros de entrada
Durante a entrada, nem todas as ações são bem-sucedidas. Por exemplo, o usuário pode tentar se conectar com um endereço de email que não existe ou enviar um código inválido.
Para lidar com erros no método
signIn(parameters:delegate)
, use o seguinte snippet de código:func onSignInStartError(error: MSAL.SignInStartError) { if error.isUserNotFound || error.isInvalidUsername { resultTextView.text = "Invalid username" } else { resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")" } }
Para lidar com erros no método
submitCode()
, use o seguinte trecho de código: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")" } }
Se o usuário inserir um código de verificação de email incorreto, o manipulador de erros incluirá uma referência a um
SignInCodeRequiredState
que poderá ser usado para enviar um código atualizado. Em nossa implementação anterior do protocoloSignInVerifyCodeDelegate
, simplesmente exibimos o erro quando tratamos a função delegadoonSignInVerifyCodeError(error:newState)
.
Ler declarações de token de ID
Depois que seu aplicativo adquirir um token de ID, você poderá recuperar as declarações associadas à conta atual. Para fazer isso, use o seguinte snippet de código:
func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
let claims = result.account.accountClaims
let preferredUsername = claims?["preferred_username"] as? String
}
A chave que você usa para acessar o valor da declaração é o nome que você especifica ao adicionar o atributo de usuário como uma declaração de token.
Saiba como adicionar atributos integrados e personalizados como declarações de token conferindo o artigo Adicionar atributos de usuário às declarações de token.
Desconectar usuário
Para desconectar um usuário, use a referência ao MSALNativeAuthUserAccountResult
que você recebeu no retorno de chamada onSignInCompleted
ou use getNativeAuthUserAccount()
para obter do cache qualquer conta conectada e armazenar uma referência na variável de membro accountResult
.
Configure o grupo de conjuntos de chaves para seu projeto, conforme descrito aqui.
Adicione uma nova variável de membro à classe
ViewController
:var accountResult: MSALNativeAuthUserAccountResult?
.Atualize
viewDidLoad
para recuperar qualquer conta armazenada em cache adicionando esta linha depois denativeAuth
ser inicializado com sucesso:accountResult = nativeAuth.getNativeAuthUserAccount()
.Atualize o manipulador
signInCompleted
para armazenar o resultado da conta:func onSignInCompleted(result: MSALNativeAuthUserAccountResult) { resultTextView.text = "Signed in successfully" accountResult = result }
Adicione um botão Sair e use o seguinte código para desconectar do usuário:
@IBAction func signOutPressed(_: Any) { guard let accountResult = accountResult else { print("Not currently signed in") return } accountResult.signOut() self.accountResult = nil resultTextView.text = "Signed out" }
Você concluiu com sucesso todas as etapas necessárias para desconectar um usuário no seu aplicativo. Compile e execute seu aplicativo. Se tudo estiver certo, você poderá selecionar o botão Sair para se desconectar com sucesso.
Configurar provedor de declarações personalizado
Se você quiser adicionar declarações a partir de um sistema externo ao token emitido para seu aplicativo, use um provedor de declarações personalizado. Um provedor de declarações personalizado é composto por uma extensão de autenticação personalizada que chama uma API REST externa para buscar declarações de sistemas externos.
Siga as etapas em Configurar um provedor de declarações personalizado para adicionar declarações de um sistema externo aos seus tokens de segurança.