チュートリアル: 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
パラメータもあります。これにより、次の 2 つの新しいメソッドにアクセスできます。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)"
}
}