教學課程:在 iOS/macOS 應用程式的自助式密碼重設
適用於: iOS (Swift)
macOS (Swift)
本教學課程示範如何讓使用者能夠變更或重設其密碼,而無需系統管理員或支援人員介入。
在本教學課程中,您會了解如何:
- 新增自助式密碼重設功能。
- 處理錯誤。
必要條件
重設密碼
若要重設現有使用者的密碼,我們必須使用一次性密碼 (OTP) 驗證電子郵件地址。
若要驗證電子郵件,我們使用下列程式碼片段,從 SDK 執行個體呼叫
resetPassword(parameters:delegate)
方法:let parameters = MSALNativeAuthResetPasswordParameters(username: email) nativeAuth.resetPassword(parameters: parameters, delegate: self)
若要將
ResetPasswordStartDelegate
通訊協定實作為類別的延伸模組,請使用下列程式碼片段:extension ViewController: ResetPasswordStartDelegate { func onResetPasswordCodeRequired( newState: MSAL.ResetPasswordCodeRequiredState, sentTo: String, channelTargetType: MSALNativeAuthChannelType, codeLength: Int ) { resultTextView.text = "Verification code sent to \(sentTo)" } func onResetPasswordStartError(error: MSAL.ResetPasswordStartError) { resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")" } }
呼叫
resetPassword(parameters:delegate)
會導致呼叫onResetPasswordCodeRequired()
或onResetPasswordStartError()
委派方法。在最常見的案例中,會呼叫
onResetPasswordCodeRequired(newState:sentTo:channelTargetType:codeLength)
來表示已傳送代碼以驗證使用者的電子郵件地址。 除了一些已傳送的代碼位置詳細資料以及代碼包含的位數之外,此委派方法還有型別newState
的ResetPasswordCodeRequiredState
參數,這可讓我們存取兩個新方法:submitCode(code:delegate)
resendCode(delegate)
若要提交使用者提供給我們的代碼,請使用:
newState.submitCode(code: userSuppliedCode, delegate: self)
若要驗證所提交的代碼,請使用下列程式碼片段,開始將
ResetPasswordVerifyCodeDelegate
通訊協定實作為類別的延伸模組:extension ViewController: ResetPasswordVerifyCodeDelegate { func onResetPasswordVerifyCodeError( error: MSAL.VerifyCodeError, newState: MSAL.ResetPasswordCodeRequiredState? ) { resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")" } func onPasswordRequired(newState: MSAL.ResetPasswordRequiredState) { // use newState instance to submit the new password } }
在最常見的案例中,我們會收到
onPasswordRequired(newState)
的呼叫,表示我們可以使用newState
執行個體提供新的密碼。newState.submitPassword(password: newPassword, delegate: self)
若要將
ResetPasswordRequiredDelegate
通訊協定實作為類別的延伸模組,請使用下列程式碼片段:extension ViewController: ResetPasswordRequiredDelegate { func onResetPasswordRequiredError( error: MSAL.PasswordRequiredError, newState: MSAL.ResetPasswordRequiredState? ) { resultTextView.text = "Error submitting new password: \(error.errorDescription ?? "no description")" } func onResetPasswordCompleted(newState: SignInAfterResetPasswordState) { resultTextView.text = "Password reset completed" } }
在最常見的案例中,我們會收到
onResetPasswordCompleted(newState)
的呼叫,表示已完成密碼重設流程。
處理錯誤
在先前的 ResetPasswordStartDelegate
通訊協定實作中,我們在處理 onResetPasswordStartError(error)
委派函式時顯示了錯誤。
我們可以藉由處理特定錯誤類型來增強使用者體驗,如下所示:
func onResetPasswordStartError(error: MSAL.ResetPasswordStartError) {
if error.isInvalidUsername {
resultTextView.text = "Invalid username"
} else if error.isUserNotFound {
resultTextView.text = "User not found"
} else if error.isUserDoesNotHavePassword {
resultTextView.text = "User is not registered with a password"
} else {
resultTextView.text = "Error during reset password flow in: \(error.errorDescription ?? "no description")"
}
}
處理具有狀態的錯誤
有些錯誤包含有新狀態參考。 例如,如果使用者輸入不正確的電子郵件驗證碼,錯誤處理常式包含有可用來提交新驗證碼的 ResetPasswordCodeRequiredState
參考。
在先前的 ResetPasswordVerifyCodeDelegate
通訊協定實作中,我們在處理 onResetPasswordError(error:newState)
委派函式時,我們僅顯示錯誤。
我們可以要求使用者輸入正確的代碼並重新提交代碼,藉此改善使用者體驗,如下所示:
func onResetPasswordVerifyCodeError(
error: MSAL.VerifyCodeError,
newState: MSAL.ResetPasswordCodeRequiredState?
) {
if error.isInvalidCode {
// Inform the user that the submitted code was incorrect and ask for a new code to be supplied.
// Request a new code calling `newState.resendCode(delegate)`
let userSuppliedCode = retrieveNewCode(newState)
newState?.submitCode(code: userSuppliedCode, delegate: self)
} else {
resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
}
}
錯誤處理常式包含有新狀態參考的另一個範例是,使用者輸入無效的密碼。 在這種情況下,錯誤處理常式包含有可用來提交新密碼的 ResetPasswordRequiredState
參考。 以下是範例:
func onResetPasswordRequiredError(
error: MSAL.PasswordRequiredError,
newState: MSAL.ResetPasswordRequiredState?
) {
if error.isInvalidPassword {
// Inform the user that the submitted password was invalid and ask for a new password to be supplied.
let newPassword = retrieveNewPassword()
newState?.submitPassword(password: newPassword, delegate: self)
} else {
resultTextView.text = "Error submitting password: \(error.errorDescription ?? "no description")"
}
}
密碼重設後登入
SDK 讓開發人員能夠在使用者重設密碼之後將其登入,而不需要提供使用者名稱,或透過一次性密碼驗證電子郵件地址。
若要在使用者成功重設密碼之後將其登入,請使用 signIn(parameters:delegate)
函式中所傳回新狀態 SignInAfterResetPasswordState
的 onResetPasswordCompleted(newState)
方法:
extension ViewController: ResetPasswordRequiredDelegate {
func onResetPasswordRequiredError(
error: MSAL.PasswordRequiredError,
newState: MSAL.ResetPasswordRequiredState?
) {
resultTextView.text = "Error submitting new password: \(error.errorDescription ?? "no description")"
}
func onResetPasswordCompleted() {
resultTextView.text = "Password reset completed"
let parameters = MSALNativeAuthSignInAfterResetPasswordParameters()
newState.signIn(parameters: parameters, delegate: self)
}
}
signIn(parameters:delegate)
接受委派參數,而且我們必須實作 SignInAfterResetPasswordDelegate
通訊協定中的必要方法。
在最常見的案例中,我們會收到 onSignInCompleted(result)
呼叫,指出使用者已登入。 此結果可用來擷取 access token
。
extension ViewController: SignInAfterSignUpDelegate {
func onSignInAfterSignUpError(error: SignInAfterSignUpError) {
resultTextView.text = "Error signing in after password reset"
}
func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
// User successfully signed in
let parameters = MSALNativeAuthGetAccessTokenParameters()
result.getAccessToken(parameters: parameters, delegate: self)
}
}
getAccessToken(parameters: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)"
}
}