教程:添加自助服务密码重置功能

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

本教程演示如何让用户在没有管理员或技术支持参与的情况下更改或重置其密码。

在本教程中,你将:

  • 添加自助式密码重置 (SSPR) 流。
  • 将 SSPR 所需的用户界面(UI)添加到应用。
  • 处理错误。

先决条件

添加自助密码重置流程

若要将 SSPR 流添加到 Android 应用程序,需要密码重置用户界面:

  • 用于收集用户电子邮件地址(用户名)的输入文本字段。
  • 用于收集一次性密码的输入文本字段。
  • 用于收集新密码的输入文本字段。

当用户忘记密码时,他们需要一个表单来输入用户名(电子邮件地址),以启动密码重置流。 用户选择 忘记密码 按钮或链接。

启动密码重置流

若要在用户选择 忘记密码 按钮或链接时处理请求,请使用 Android SDK 的 resetPassword(parameters) 方法,如以下代码片段所示:

 private fun forgetPassword() { 
     CoroutineScope(Dispatchers.Main).launch { 
         val parameter = NativeAuthResetPasswordParameters(username = email)
         val actionResult = authClient.resetPassword(parameter)

         when (resetPasswordResult) { 
             is ResetPasswordStartResult.CodeRequired -> { 
                 // The implementation of submitCode() please see below. 
                 submitCode(resetPasswordResult.nextState) 
             } 
             is ResetPasswordError -> {
                 // Handle errors
                 handleResetPasswordError(resetPasswordResult)
             }
         }
     } 
 } 
  • resetPassword(parameters) 方法启动密码重置流,并将一次性密码发送到用户的电子邮件地址进行验证。

  • resetPassword(parameters) 的返回结果为 ResetPasswordStartResult.CodeRequiredResetPasswordError

  • 如果 resetPasswordResult is ResetPasswordStartResult.CodeRequired,应用需要从用户收集一次性密码并将其提交,如 提交电子邮件一次性密码所示。

  • 如果 resetPasswordResult is ResetPasswordError,Android SDK 提供了实用工具方法来进一步分析特定错误: - isUserNotFound()- isBrowserRequired()

  • 这些错误表示上一个操作失败,因此对新状态的引用不可用。 如处理错误部分所示,处理这些错误。

通过电子邮件提交一次性密码

你的应用从用户收集电子邮件一次性密码。 若要提交电子邮件一次性密码,请使用以下代码片段:

private suspend fun submitCode(currentState: ResetPasswordCodeRequiredState) { 
    val code = binding.codeText.text.toString() 
    val submitCodeResult = currentState.submitCode(code) 

    when (submitCodeResult) { 
        is ResetPasswordSubmitCodeResult.PasswordRequired -> { 
            // Handle success
            resetPassword(submitCodeResult.nextState) 
        } 
         is SubmitCodeError -> {
             // Handle errors
             handleSubmitCodeError(actionResult)
         }
    } 
} 
  • submitCode()作的返回结果为 ResetPasswordSubmitCodeResult.PasswordRequiredSubmitCodeError

  • 如果 submitCodeResult is ResetPasswordSubmitCodeResult.PasswordRequired,应用需要从用户处收集新密码,并如提交新密码所示提交新密码。

  • 如果用户的电子邮件中未收到电子邮件一次性密码,应用可以重新发送电子邮件一次性密码。 使用以下代码片段重新发送新电子邮件一次性密码:

    private fun resendCode() { 
         clearCode() 
    
         val currentState = ResetPasswordCodeRequiredState 
    
         CoroutineScope(Dispatchers.Main).launch { 
             val resendCodeResult = currentState.resendCode() 
    
             when (resendCodeResult) { 
                 is ResetPasswordResendCodeResult.Success -> { 
                     // Handle code resent success
                 } 
                 is ResendCodeError -> {
                      // Handle ResendCodeError errors
                  }
             } 
         } 
    } 
    
    • resendCode()作的返回结果为 ResetPasswordResendCodeResult.SuccessResendCodeError

    • SDK 的 ResendCodeError 是一个意外错误。 此错误表示上一个操作失败,因此无法获得对新状态的引用。

  • 如果 submitCodeResult is SubmitCodeError,Android SDK 提供了实用工具方法来进一步分析特定错误:

    • isInvalidCode()
    • isBrowserRequired()

    这些错误表示上一个操作失败,因此对新状态的引用不可用。 如处理错误部分所示,处理这些错误。

提交新密码

验证用户的电子邮件后,需要从用户那里收集新密码并提交。 应用从用户那里收集的密码需要满足 Microsoft Entra 的密码策略。 使用以下代码片段:

private suspend fun resetPassword(currentState: ResetPasswordPasswordRequiredState) { 
    val password = binding.passwordText.text.toString() 

    val submitPasswordResult = currentState.submitPassword(password) 

    when (submitPasswordResult) { 
        is ResetPasswordResult.Complete -> { 
            // Handle reset password complete. 
        } 
        is ResetPasswordSubmitPasswordError -> {
            // Handle errors
            handleSubmitPasswordError(actionResult)
        }
    } 
} 
  • submitPassword()作的返回结果为 ResetPasswordResult.CompleteResetPasswordSubmitPasswordError

  • ResetPasswordResult.Complete 指示密码重置流成功。

  • 如果 submitPasswordResult is ResetPasswordSubmitPasswordError,SDK 提供了实用工具方法,用于进一步分析返回的特定错误类型: - isInvalidPassword()- isPasswordResetFailed()

    这些错误表示上一个操作失败,因此对新状态的引用不可用。 如处理错误部分所示,处理这些错误。

密码重置后自动登录

成功密码重置流后,无需启动新的登录流即可自动登录用户。

ResetPasswordResult.Complete 返回 SignInContinuationState 对象。 SignInContinuationState 提供对 signIn(parameters) 方法的访问权限。

若要在密码重置后自动登录用户,请使用以下代码片段:

 private suspend fun resetPassword(currentState: ResetPasswordPasswordRequiredState) { 
     val submitPasswordResult = currentState.submitPassword(password) 
 
     when (submitPasswordResult) { 
         is ResetPasswordResult.Complete -> { 
             signInAfterPasswordReset(nextState = actionResult.nextState)
         } 
     } 
 } 
 
 private suspend fun signInAfterPasswordReset(nextState: SignInContinuationState) {
     val signInContinuationState = nextState

     val parameters = NativeAuthSignInContinuationParameters()
     val signInActionResult = signInContinuationState.signIn(parameters)

     when (actionResult) {
         is SignInResult.Complete -> {
             fetchTokens(accountState = actionResult.resultValue)
         }
         else {
             // Handle unexpected error
         }
     }
  }
 
 private suspend fun fetchTokens(accountState: AccountState) {
     val getAccessTokenParameters = NativeAuthGetAccessTokenParameters()
     val accessTokenResult = accountState.getAccessToken(getAccessTokenParameters)

     if (accessTokenResult is GetAccessTokenResult.Complete) {
         val accessToken =  accessTokenResult.resultValue.accessToken
         val idToken = accountState.getIdToken()
     }
 }

若要在登录后检索 ID 令牌声明,请使用读取 ID 令牌声明中的步骤。

处理密码重置错误

可能会出现一些预期错误。 例如,用户可能尝试使用不存在的电子邮件重置密码,或者提供不符合密码要求的密码。

发生错误时,向用户提供错误提示。

这些错误可能发生在密码重置流程的开始,或在提交电子邮件一次性密码时,或在提交密码时。

处理启动密码重置错误

若要处理启动密码重置导致的错误,请使用以下代码片段:

private fun handleResetPasswordError(error: ResetPasswordError) {
    when {
        error.isUserNotFound() -> {
            // Display error
        }
        else -> {
            // Unexpected error
        }
    }
}

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

若要处理提交电子邮件一次性密码导致的错误,请使用以下代码片段:

private fun handleSubmitCodeError(error: SubmitCodeError) {
    when {
        error.isInvalidCode() -> {
            // Display error
        }
        else -> {
            // Unexpected error
        }
    }
}

处理提交密码错误

若要处理提交密码导致的错误,请使用以下代码片段:

private fun handleSubmitPasswordError(error: ResetPasswordSubmitPasswordError) {
    when {
        error.isInvalidPassword() || error.isPasswordResetFailed()
        -> {
            // Display error
        }
        else -> {
            // Unexpected error
        }
    }
}

后续步骤

教程:在 Android 应用中支持 Web 回退