适用于:
外部租户(了解详细信息)
本教程介绍如何使用本机身份验证 JavaScript SDK 在 React 单页应用中启用密码重置。
在本教程中,你将:
- 更新 React 应用以重置用户的密码。
- 测试密码重置流
先决条件
- 完成教程中的步骤 :使用本机身份验证 JavaScript SDK 将用户注册到 React 单页应用中。
- 为外部租户中的客户用户启用自助密码重置(SSPR)。 对于将电子邮件与密码身份验证流配合使用的应用,SSPR 适用于客户用户。
创建 UI 组件
在密码重置流期间,此应用收集用户的用户名(电子邮件)、一次性密码,以及不同屏幕上的新用户密码。 在本部分中,将创建收集应用重置密码所需的信息的表单。
创建名为 src/app/reset-password 的文件夹。
创建 reset-password/components/InitialForm.tsx 文件,然后粘贴 reset-password/components/InitialForm.tsx 中的代码。 此组件显示收集用户用户名(电子邮件)的窗体。
创建 reset-password/components/CodeForm.tsx 文件,然后粘贴 reset-password/components/CodeForm.tsx 中的代码。 此组件显示一个表单,用于收集用户在电子邮件收件箱中收到的一次性密码。
创建 reset-password/components/NewPasswordForm.tsx 文件,然后粘贴 reset-password/components/NewPasswordForm.tsx 中的代码。 此组件显示收集用户新密码的窗体。
处理表单交互
创建 reset-password/page.tsx 文件以处理登录流的逻辑。 在此文件中:
导入必要的组件,并根据状态显示正确的窗体。 请参阅 reset-password/page.tsx 中的完整示例:
import { CustomAuthPublicClientApplication, ICustomAuthPublicClientApplication, ResetPasswordCodeRequiredState, ResetPasswordPasswordRequiredState, ResetPasswordCompletedState, AuthFlowStateBase, } from "@azure/msal-browser/custom-auth"; export default function ResetPassword() { const [app, setApp] = useState<ICustomAuthPublicClientApplication | null>( null ); const [loadingAccountStatus, setLoadingAccountStatus] = useState(true); const [isSignedIn, setSignInState] = useState(false); const [email, setEmail] = useState(""); const [code, setCode] = useState(""); const [newPassword, setNewPassword] = useState(""); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [resetState, setResetState] = useState<AuthFlowStateBase | null>( null ); useEffect(() => { const initializeApp = async () => { const appInstance = await CustomAuthPublicClientApplication.create( customAuthConfig ); setApp(appInstance); }; initializeApp(); }, []); useEffect(() => { const checkAccount = async () => { if (!app) return; const accountResult = app.getCurrentAccount(); if (accountResult.isCompleted()) { setSignInState(true); } setLoadingAccountStatus(false); }; checkAccount(); }, [app]); const renderForm = () => { if (loadingAccountStatus) { return; } if (isSignedIn) { return ( <div style={styles.signed_in_msg}> Please sign out before processing the password reset. </div> ); } if (resetState instanceof ResetPasswordPasswordRequiredState) { return ( <NewPasswordForm onSubmit={handleNewPasswordSubmit} newPassword={newPassword} setNewPassword={setNewPassword} loading={loading} /> ); } if (resetState instanceof ResetPasswordCodeRequiredState) { return ( <CodeForm onSubmit={handleCodeSubmit} code={code} setCode={setCode} loading={loading} /> ); } if (resetState instanceof ResetPasswordCompletedState) { return <ResetPasswordResultPage />; } return ( <InitialForm onSubmit={handleInitialSubmit} email={email} setEmail={setEmail} loading={loading} /> ); }; return ( <div style={styles.container}> <h2 style={styles.h2}>Reset Password</h2> {renderForm()} {error && <div style={styles.error}>{error}</div>} </div> ); }若要启动密码重置流,请使用以下代码片段。 请参阅 reset-password/page.tsx 的完整示例,了解如何放置代码片段的位置:
const handleInitialSubmit = async (e: React.FormEvent) => { if (!app) return; e.preventDefault(); setError(""); setLoading(true); const result = await app.resetPassword({ username: email, }); const state = result.state; if (result.isFailed()) { if (result.error?.isInvalidUsername()) { setError("Invalid email address"); } else if (result.error?.isUserNotFound()) { setError("User not found"); } else { setError( result.error?.errorData.errorDescription || "An error occurred while initiating password reset" ); } } else { setResetState(state); } setLoading(false); };SDK 的实例方法
resetPassword()启动密码重置流。若要提交一次性密码,请使用以下代码片段。 请参阅 reset-password/page.tsx 的完整示例,了解如何放置代码片段的位置:
const handleCodeSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); if (resetState instanceof ResetPasswordCodeRequiredState) { const result = await resetState.submitCode(code); const state = result.state; if (result.isFailed()) { if (result.error?.isInvalidCode()) { setError("Invalid verification code"); } else { setError(result.error?.errorData.errorDescription || "An error occurred while verifying the code"); } } else { setResetState(state); } } setLoading(false); };密码重置状态
submitCode()提交一次性密码。若要提交用户的新密码,请使用以下代码片段。 请参阅 reset-password/page.tsx 的完整示例,了解如何放置代码片段的位置:
const handleNewPasswordSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); if (resetState instanceof ResetPasswordPasswordRequiredState) { const result = await resetState.submitNewPassword(newPassword); const state = result.state; if (result.isFailed()) { if (result.error?.isInvalidPassword()) { setError("Invalid password"); } else { setError(result.error?.errorData.errorDescription || "An error occurred while setting new password"); } } else { setResetState(state); } } setLoading(false); };密码重置状态
submitNewPassword()提交用户的新密码。若要使用重置密码结果,请使用以下代码片段。 请参阅 reset-password/page.tsx 的完整示例,了解如何放置代码片段的位置:
if (resetState instanceof ResetPasswordCompletedState) { return <ResetPasswordResultPage/>; }
可选:密码重置后自动登录用户
用户成功重置其密码后,无需启动新的登录流即可直接登录到应用。 为此,请使用以下代码片段。 请参阅 reset-password/page.tsx 的完整示例:
if (resetState instanceof ResetPasswordCompletedState) {
const result = await resetState.signIn();
const state = result.state;
if (result.isFailed()) {
setError(result.error?.errorData?.errorDescription || "An error occurred during auto sign-in");
}
if (result.isCompleted()) {
setData(result.data);
setResetState(state);
}
}
运行并测试应用
使用 “运行”中的步骤并测试应用 以运行应用,然后测试登录流。