适用于:
外部租户(了解详细信息)
本教程演示如何在 Android 移动应用中使用本机身份验证,通过电子邮件一次性密码或用户名和密码登录和注销用户。
在本教程中,你将:
- 使用电子邮件一次性密码或用户名(电子邮件)和密码登录用户。
- 注销用户。
- 处理登录错误
先决条件
- 完成教程:准备 Android 应用来进行本机身份验证中的步骤。 本教程介绍如何准备 Android 项目或应用进行本机身份验证。
用户登录
若要使用一次性密码登录用户,请收集电子邮件并发送电子邮件,其中包含一次性密码供用户验证其电子邮件。 当用户输入有效的一次性密码时,应用会登录用户。
若要使用用户名(电子邮件)和密码登录用户,请从用户收集电子邮件和密码。 如果用户名和密码有效,应用将登录用户。
若要登录用户,需要:
创建用户界面 (UI) 以:
- 从用户处收集电子邮件。 向输入添加验证,以确保用户输入有效的电子邮件地址。
- 如果使用用户名(电子邮件)和密码登录,请收集密码。
- 如果使用电子邮件一次性密码登录,请从用户收集电子邮件一次性密码。
- 如果使用电子邮件一次性密码登录,请重新发送一次性密码(建议)。
在 UI 中添加一个按钮,其选择事件会启动登录,如以下代码片段所示:
CoroutineScope(Dispatchers.Main).launch { val parameters = NativeAuthSignInParameters(username = email) // Assign 'password' param if you sign in with username (email) and password // parameters.password = password val actionResult: SignInResult = authClient.signIn(parameters) if (actionResult is SignInResult.CodeRequired) { val nextState = actionResult.nextState val submitCodeActionResult = nextState.submitCode( code = code ) if (submitCodeActionResult is SignInResult.Complete) { // Handle sign in success val accountState = submitCodeActionResult.resultValue val getAccessTokenParameters = NativeAuthGetAccessTokenParameters() val accessTokenResult = accountState.getAccessToken(getAccessTokenParameters) if (accessTokenResult is GetAccessTokenResult.Complete) { val accessToken = accessTokenResult.resultValue.accessToken val idToken = accountState.getIdToken() } } } }如果用户不需要提交密码(例如用户使用电子邮件和密码登录的情况),请使用以下代码片段:
CoroutineScope(Dispatchers.Main).launch { val parameters = NativeAuthSignInParameters(username = email) parameters.password = password val actionResult: SignInResult = authClient.signIn(parameters) if (actionResult is SignInResult.Complete) -> { // Handle sign in success val accountState = actionResult.resultValue val getAccessTokenParameters = NativeAuthGetAccessTokenParameters() val accessTokenResult = accountState.getAccessToken(getAccessTokenParameters) if (accessTokenResult is GetAccessTokenResult.Complete) { val accessToken = accessTokenResult.resultValue.accessToken val idToken = accountState.getIdToken() } } }- 若要启动登录流,请使用 SDK 的
signIn(parameters)方法。 -
NativeAuthSignInParameters类的实例,包含从用户收集的电子邮件地址username。 - 如果登录方法是用户名(电子邮件)和密码,则该方法的参数
password是从用户那里收集的密码。 - 在最常见的方案中,
signIn(parameters)返回一个结果,SignInResult.CodeRequired,这表示 SDK 要求应用提交发送到用户电子邮件地址的电子邮件一次性密码。 -
SignInResult.CodeRequired对象包含一个新的状态引用,我们可以通过actionResult.nextState来检索该引用。 - 新状态允许我们使用两种新方法:
-
submitCode()会提交应用从用户那里收集的电子邮件一次性密码。 - 如果用户没有收到电子邮件一次性密码,
resendCode()会重新发送它。
-
- 若要启动登录流,请使用 SDK 的
处理登录错误
登录过程中,并非所有操作都会成功。 例如,用户可能尝试使用不存在的电子邮件地址登录,或提交无效密码。
处理登录启动错误
若要处理 signIn(parameters) 方法中的错误,请使用以下代码片段:
val parameters = NativeAuthSignInParameters(username = email)
// Assign 'password' param if you sign in with username (email) and password
// parameters.password = password
val actionResult: SignInResult = authClient.signIn(parameters)
if (actionResult is SignInResult.CodeRequired) {
// Next step: submit code
} else if (actionResult is SignInError) {
// Handle sign in errors
when {
actionResult.isUserNotFound() -> {
// Handle "user not found" error
}
actionResult.isAuthNotSupported() -> {
// Handle "authentication type not support" error
}
actionResult.isInvalidCredentials() -> {
// Handle specific errors
}
else -> {
// Handle other errors
}
}
}
-
SignInError指示signIn(parameters)返回的操作结果失败,因此操作结果不包括对新状态的引用。 - 如果返回的是
actionResult is SignUpError,Android SDK 会提供实用工具方法来让你能够进一步分析特定错误:- 方法
isUserNotFound()会检查用户是否在使用不存在的用户名(电子邮件地址)登录。 - 方法
isBrowserRequired()会检查是否需要浏览器(Web 回退)来完成身份验证流。 当本机身份验证不足以完成身份验证流时,会出现这种情况。 例如,管理员将电子邮件和密码配置为身份验证方法,但应用未发送 password 作为质询类型,或者根本不支持该质询类型。 使用在 Android 应用中支持 Web 回退中的步骤来处理发生这种情况的场景。 - 方法
isAuthNotSupported()会检查应用是否发送 Microsoft Entra 不支持的质询类型,即除 oob 和 password 以外的质询类型值。 详细了解 挑战类型。 - 对于用户名(电子邮件)和密码登录,方法
isInvalidCredentials()会检查用户名和密码的组合是否正确。
- 方法
处理提交代码错误
若要处理 submitCode() 方法中的错误,请使用以下代码片段:
val submitCodeActionResult = nextState.submitCode(
code = code
)
if (submitCodeActionResult is SignInResult.Complete) {
// Sign in flow complete, handle success state.
} else if (submitCodeActionResult is SubmitCodeError && submitCodeActionResult.isInvalidCode()) {
// Handle "invalid code" error
}
-
SubmitCodeError错误表示submitCode()返回的操作结果不成功,因此操作结果不包含对新状态的引用。 -
isInvalidCode()会检查特定错误。 在这种情况下,必须使用以前的状态引用来重新执行操作。
若要检索新的电子邮件一次性密码,请使用以下代码片段:
val submitCodeActionResult = nextState.submitCode(
code = code
)
if (submitCodeActionResult is SignInError && submitCodeActionResult.isInvalidCode) {
// Inform the user that the submitted code was incorrect or invalid, then ask them to input a new email one-time passcode
val newCode = retrieveNewCode()
nextState.submitCode(
code = newCode
)
}
你已完成在应用上成功登录用户所需的所有步骤。 生成并运行应用程序。 如果一切正常,你应该能够提供电子邮件、通过电子邮件接收密码,并使用该密码成功登录用户。
读取 ID 令牌声明
一旦应用获取了 ID 令牌,即可检索与当前帐户关联的声明。 为此,请使用以下代码片段。
val preferredUsername = accountState.getClaims()?.get("preferred_username")
val city = accountState.getClaims()?.get("City")
val givenName = accountState.getClaims()?.get("given_name")
//custom attribute
val loyaltyNumber = accountState.getClaims()?.get("loyaltyNumber")
用于访问声明值的密钥是你在将用户属性添加为令牌声明时指定的名称。
若要了解如何将内置属性和自定义属性添加为令牌声明,请参阅将用户属性添加到令牌声明一文。
将用户注销
若要将用户退出登录,需要删除当前存储在缓存中的帐户。
创建包括以下内容的自定义用户界面 (UI):
- 一个退出登录按钮,用户选择它后可以发送退出登录请求。
若要注销用户,请使用以下代码:
private fun performSignOut(accountState: AccountState) { CoroutineScope(Dispatchers.Main).launch { val accountResult = authClient.getCurrentAccount() if (accountResult is GetAccountResult.AccountFound) { val signOutResult = accountResult.resultValue.signOut() if (signOutResult is SignOutResult.Complete) { // Show sign out successful UI } } } }
处理退出登录错误
注销不应出现错误。 如果发生任何错误,请使用以下代码片段检查错误结果:
val actionResult = accountResult.signOut()
if (actionResult is SignOutResult.Complete) {
// Show sign out successful UI
} else {
// Handle errors
}
确保包含 import 语句。 Android Studio 应该会自动为你添加 import 语句。
你已完成在应用中成功注销用户所需的所有步骤。 生成并运行应用程序。 如果一切正常,则应能选择“注销”按钮以成功注销。
配置自定义声明提供程序
如果要将来自外部系统的声明添加到颁发给应用的令牌中,请使用 自定义声明提供程序。 自定义声明提供程序由自定义身份验证扩展组成,它会调用外部 REST API 来从外部系统提取声明。
按照 配置自定义声明提供程序 中的步骤将外部系统中的声明添加到安全令牌中。
使用别名或用户名启用登录
你可以允许使用电子邮件地址和密码登录的用户也使用用户名和密码登录。 用户名也称为备用登录标识符,可以是客户 ID、帐户号或你选择用作用户名的另一个标识符。
可以通过 Microsoft Entra 管理中心手动将用户名分配给用户帐户,或者通过 Microsoft 图形 API 在应用中自动分配用户名。
使用 别名或用户名登录 文章中的步骤,以允许用户在您的应用程序中使用用户名登录: