다음을 통해 공유


자습서: 네이티브 인증 JavaScript SDK를 사용하여 React 단일 페이지 앱에서 암호 재설정

적용 대상: 외부 테넌트에 다음 내용이 적용되었음을 나타내는 흰색 확인 표시 기호가 있는 녹색 원입니다. 외부 테넌트(자세한 정보)

이 자습서에서는 네이티브 인증 JavaScript SDK를 사용하여 React 단일 페이지 앱에서 암호 재설정을 사용하도록 설정하는 방법을 알아봅니다.

이 자습서에서는 다음을 수행합니다.

  • React 앱을 업데이트하여 사용자의 암호를 재설정합니다.
  • 암호 재설정 흐름 테스트

필수 조건

UI 구성 요소 만들기

암호 재설정 흐름 중에 이 앱은 다른 화면에서 사용자의 사용자 이름(이메일), 일회성 암호 및 새 사용자 암호를 수집합니다. 이 섹션에서는 앱이 암호를 재설정하는 데 필요한 정보를 수집하는 양식을 만듭니다.

  1. src/app/reset-password라는 폴더를 만듭니다.

  2. reset-password/components/InitialForm.tsx 파일을 만든 다음 reset-password/components/InitialForm.tsx의 코드를 붙여넣습니다. 이 구성 요소는 사용자의 사용자 이름(이메일)을 수집하는 양식을 표시합니다.

  3. reset-password/components/CodeForm.tsx 파일을 만든 다음 reset-password/components/CodeForm.tsx의 코드를 붙여넣습니다. 이 구성 요소는 사용자가 전자 메일 받은 편지함에서 받는 일회용 암호를 수집하는 양식을 표시합니다.

  4. 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);
    }
}

앱 실행 및 테스트

실행의 단계를 사용하고 앱을 테스트 하여 앱을 실행한 다음 로그인 흐름을 테스트합니다.