教程:使用本机身份验证在 Android 移动应用中添加注册

适用于:带灰色 X 号的白色圆圈。 员工租户 带白色对号的绿色圆圈。 外部租户(了解详细信息

本教程演示如何使用本机身份验证在 Android 应用中通过电子邮件一次性密码或用户名(电子邮件)和密码来注册用户并收集用户属性。

在本教程中,你将:

  • 使用电子邮件一次性密码或用户名(电子邮件)和密码注册用户。
  • 在注册期间收集用户属性。
  • 处理注册错误。

先决条件

注册用户

若要使用电子邮件一次性密码或用户名(电子邮件)和密码注册用户,请从用户那里收集电子邮件,然后向用户发送包含电子邮件一次性密码的电子邮件。 用户输入有效的电子邮件一次性密码以验证其用户名。

若要注册用户,需要:

  1. 创建用户界面 (UI) 以:

    • 从用户处收集电子邮件。 向输入添加验证,以确保用户输入有效的电子邮件地址。
    • 如果使用用户名(电子邮件)和密码注册,请收集密码。
    • 从用户处收集电子邮件一次性密码。
    • 如果需要,收集用户属性。
    • 重新发送一次性密码(推荐)。
    • 开始注册流程。
  2. 在应用中添加一个按钮,其选择事件会触发以下代码片段:

    CoroutineScope(Dispatchers.Main).launch {
         val parameters = NativeAuthSignUpParameters(username = email)
         // Assign 'password' param if you sign in with username (email) and password
         // parameters.password = password
         val actionResult: SignUpResult = authClient.signUp(parameters)
    
         if (actionResult is SignUpResult.CodeRequired) {
             val nextState = actionResult.nextState
             val submitCodeActionResult = nextState.submitCode(
                code = code
             )
             if (submitCodeActionResult is SignUpResult.Complete) {
                // Handle sign up success
             }
        }
    }
    
    • 使用 SDK 的 signUp(parameters) 实例方法启动注册流。
    • 若要使用用户名(电子邮件地址)和密码注册,请创建 NativeAuthSignUpParameters 类的实例,并分配用户名和密码。
    • 注册参数 username是从用户那里收集的电子邮件地址。
    • 在最常见的方案中,signUp(parameters) 返回一个结果,SignUpResult.CodeRequired,这表示 SDK 要求应用提交发送到用户电子邮件地址的电子邮件一次性密码。
    • SignUpResult.CodeRequired 对象包含一个新的状态引用,我们可以通过 actionResult.nextState 来检索该引用。
    • 新状态允许我们使用两种新方法:
      • submitCode() 会提交应用从用户那里收集的电子邮件一次性密码。
      • 如果用户没有收到电子邮件一次性密码,resendCode() 会重新发送它。
    • submitCode() 会返回 SignUpResult.Complete,这指示流已完成且用户已注册。
    • signUp(parameters) 还可以返回 SignUpError 来表示发生了错误。

在注册期间收集用户属性

无论是使用电子邮件一次性密码还是用户名(电子邮件)和密码注册用户,都可以在创建用户帐户之前收集用户属性:

  • NativeAuthSignUpParameters 实例接受 attributes 参数:

        CoroutineScope(Dispatchers.Main).launch {
            val parameters = NativeAuthSignUpParameters(username = email)
            // Assign 'password' param if you sign in with username (email) and password
            // parameters.password = password
            parameters.attributes = userAttributes
            val actionResult: SignUpResult = authClient.signUp(parameters)
            //...
        }
    
  • Android SDK 提供实用工具类 UserAttribute.Builder,用于创建用户属性。 例如,若要提交 citycountry 用户属性,请使用以下代码片段生成 userAttributes 变量:

         val userAttributes = UserAttributes.Builder ()
        .country(country) 
        .city(city) 
        .build()   
    

    UserAttribute.Builder 类中的方法名称与其构建的用户属性的可编程名称相同。 详细了解 Android SDK 属性生成器

  • signUp(parameters) 方法可以返回 SignUpResult.AttributesRequired,以指示应用需要在Microsoft Entra 创建帐户之前提交一个或多个必需属性。 管理员将这些属性配置为 Microsoft Entra 管理中心中的必需属性。 Microsoft Entra 不会明确请求可选用户属性。

  • SignUpResult.AttributesRequired 结果包含 requiredAttributes 参数。 requiredAttributesRequiredUserAttribute 对象的列表,其中包含有关用户属性的详细信息,应用需要提交这些属性。 若要处理 actionResult is SignUpResult.AttributesRequired,请使用以下代码片段:

    val parameters = NativeAuthSignUpParameters(username = email)
    // Assign 'password' param if you sign in with username (email) and password
    // parameters.password = password
    parameters.attributes = userAttributes
    val actionResult: SignUpResult = authClient.signUp(parameters)
    
    if (actionResult is SignUpResult.AttributesRequired) {
            val requiredAttributes = actionResult.requiredAttributes 
            // Handle "attributes required" result 
            val nextState = actionResult.nextState
            nextState.submitAttributes(
                attributes = moreAttributes
            )
    }
    

处理注册错误

在注册期间,并非所有操作都能成功。 例如,用户可能会尝试使用已使用的电子邮件地址进行注册或提交无效的电子邮件一次性密码。

处理启动注册错误

若要处理 signUp() 方法的错误,请使用以下代码片段:

 val parameters = NativeAuthSignUpParameters(username = email)
 // Assign 'password' param if you sign in with username (email) and password
 // parameters.password = password
val actionResult: SignUpResult = authClient.signUp(parameters)

if (actionResult is SignUpResult.CodeRequired) {
    // Next step: submit code
} else if (actionResult is SignUpError) {
     when {
         actionResult.isUserAlreadyExists() -> {
             // Handle "user already exists" error
         }
         else -> {
             // Handle other errors
         }
     }
}
  • signUp(parameters) 可以返回 SignUpError

  • SignUpError 表示 signUp() 返回的操作结果不成功,因此不包含对新状态的引用。

  • 如果返回的是 actionResult is SignUpError,MSAL Android SDK 提供实用工具方法来进一步分析特定错误:

    • 方法 isUserAlreadyExists() 会检查用户名是否已被用于创建帐户。
    • isInvalidAttributes() 会检查应用提交的一个或多个属性是否未通过验证,例如出现错误的数据类型。 它包含一个 invalidAttributes 参数,该参数是应用提交的但未通过验证的所有属性的列表。
    • isInvalidPassword() 会检查密码是否无效,例如当密码不符合所有密码复杂性要求时。 详细了解 Microsoft Entra 的密码策略
    • isInvalidUsername() 会检查用户名是否无效,例如当用户电子邮件无效时。
    • isBrowserRequired() 会检查是否需要浏览器(Web 回退)来完成身份验证流。 当本机身份验证不足以完成身份验证流时,会出现这种情况。 例如,管理员将电子邮件和密码配置为身份验证方法,但应用未发送 password 作为质询类型,或者根本不支持该质询类型。 使用在 Android 应用中支持 Web 回退中的步骤来处理发生这种情况的场景。
    • isAuthNotSupported() 会检查应用是否在发送 Microsoft Entra 不支持的质询类型,即除 oob 或 password 以外的质询类型值。 详细了解挑战类型

    通过应用 UI 中的友好消息通知用户电子邮件已在使用中,或者某些属性无效。

  • 若要处理属性无效错误,请使用以下代码片段:

    val parameters = NativeAuthSignUpParameters(username = email)
    // Assign 'password' param if you sign in with username (email) and password
    // parameters.password = password
    parameters.attributes = userAttributes
    val actionResult: SignUpResult = authClient.signUp(parameters)
    
    if (actionResult is SignUpError && actionResult.isInvalidAttributes()) {
        val invalidAttributes = actionResult.invalidAttributes
    
        // Handle "invalid attributes" error, this time submit valid attributes
        val parameters = NativeAuthSignUpParameters(username = email)
        // Assign 'password' param if you sign in with username (email) and password
        // parameters.password = password
        parameters.attributes = userAttributes
        authClient.signUp(parameters)
    } 
    //...
    

处理提交电子邮件一次性密码错误

若要处理 submitCode() 方法的错误,请使用以下代码片段:

val submitCodeActionResult = nextState.submitCode(
    code = code
)
if (submitCodeActionResult is SignUpResult.Complete) {
    // Sign up flow complete, handle success state.
} else if (submitCodeActionResult is SubmitCodeError) {
    // Handle errors under SubmitCodeError
     when {
         submitCodeActionResult.isInvalidCode() -> {
             // Handle "code invalid" error
         }
         else -> {
             // Handle other errors
         }
     }
}
  • submitCode() 可以返回 SubmitCodeError

  • 使用 isInvalidCode() 方法检查特定错误,例如“提交的代码无效”。 在这种情况下,必须使用以前的状态引用来重新执行操作。

  • 若要检索新的电子邮件一次性密码,请使用以下代码片段:

    val submitCodeActionResult = nextState.submitCode(
        code = code
    )
    if (submitCodeActionResult is SubmitCodeError && submitCodeActionResult.isInvalidCode()) {
        // Inform the user that the submitted code was incorrect or invalid and ask for a new code to be supplied
        val newCode = retrieveNewCode()
        nextState.submitCode(
            code = newCode
        )
    }
    

确保包含 import 语句。 Android Studio 应该会自动为你添加 import 语句。

你已完成将用户成功注册到应用中所需的所有步骤。 生成并运行应用程序。 如果一切正常,你应能够使用电子邮件一次性密码或电子邮件和密码成功注册用户。

可选:注册流程完成后登录

注册流成功后,你可以登录用户,而无需启动登录流。 请在教程:在 Android 中注册后登录用户一文中了解详细信息。

后续步骤

教程:在 Android 应用中添加使用电子邮件一次性密码进行登录和退出登录的功能