次の方法で共有


チュートリアル: 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) が呼び出されます。 このデリゲート メソッドには、コードが送信された場所と、コードに含まれる桁数の詳細に加えて、newState 型の ResetPasswordCodeRequiredState パラメータもあります。これにより、次の 2 つの新しいメソッドにアクセスできます。

    • 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)"
    }
}

次のステップ