共用方式為


教學課程:在 iOS/macOS 應用程式的自助式密碼重設

適用於內含白色核取記號的綠色圓圈。 iOS (Swift) 具有白色核取符號的綠色圓圈。 macOS (Swift)

本教學課程示範如何讓使用者能夠變更或重設其密碼,而無需系統管理員或支援人員介入。

在本教學課程中,您會了解如何:

  • 新增自助式密碼重設功能。
  • 處理錯誤。

必要條件

重設密碼

若要重設現有使用者的密碼,我們必須使用一次性密碼 (OTP) 驗證電子郵件地址。

  1. 若要驗證電子郵件,我們使用下列程式碼片段,從 SDK 執行個體呼叫 resetPassword(parameters:delegate) 方法:

    let parameters = MSALNativeAuthResetPasswordParameters(username: email)
    nativeAuth.resetPassword(parameters: parameters, delegate: self)
    
  2. 若要將 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) 來表示已傳送代碼以驗證使用者的電子郵件地址。 除了一些已傳送的代碼位置詳細資料以及代碼包含的位數之外,此委派方法還有型別 newStateResetPasswordCodeRequiredState 參數,這可讓我們存取兩個新方法:

    • submitCode(code:delegate)
    • resendCode(delegate)

    若要提交使用者提供給我們的代碼,請使用:

    newState.submitCode(code: userSuppliedCode, delegate: self)
    
  3. 若要驗證所提交的代碼,請使用下列程式碼片段,開始將 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)
    
  4. 若要將 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) 函式中所傳回新狀態 SignInAfterResetPasswordStateonResetPasswordCompleted(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)"
    }
}

後續步驟