共用方式為


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

適用於帶有白色核取記號符號的綠色圓圈,表示下列內容適用於外部租用戶。 外部租用戶 (深入瞭解

本教學課程示範如何為使用者提供變更或重設其密碼的能力,而不需要系統管理員或技術支援中心介入。

在本教學課程中,您會:

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

先決條件

重設密碼

若要重設現有使用者的密碼,我們需要使用一次性密碼 (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)"
    }
}

下一步