비밀번호 찾기 및 재설정 처리
비밀번호 찾기 및 재설정 처리
우리의 서버리스 노트 앱에서는 사용자 가입 및 로그인을 위해 Cognito 사용자 풀을 사용했습니다. 프론트엔드에서는 React 앱에서 AWS Amplify를 사용했습니다. 그러나 사용자가 비밀번호를 잊어버린 경우, 비밀번호를 재설정할 수 있는 방법이 필요합니다. 이번 장에서는 이를 어떻게 구현하는지 살펴보겠습니다.
이 장에서 사용된 노트 앱 버전은 별도의 GitHub 저장소에 호스팅되어 있습니다: https://github.com/AnomalyInnovations/serverless-stack-demo-user-mgmt-client.
사용자가 비밀번호를 재설정할 수 있도록 하기 위해 필요한 주요 변경 사항을 살펴보겠습니다.
비밀번호 재설정 폼 추가하기
src/containers/ResetPassword.js
파일을 생성합니다.
import React, { useState } from "react";
import { Auth } from "aws-amplify";
import { Link } from "react-router-dom";
import {
FormText,
FormGroup,
FormControl,
FormLabel,
} from "react-bootstrap";
import { BsCheck } from "react-icons/bs";
import LoaderButton from "../components/LoaderButton";
import { useFormFields } from "../lib/hooksLib";
import { onError } from "../lib/errorLib";
import "./ResetPassword.css";
export default function ResetPassword() {
const [fields, handleFieldChange] = useFormFields({
code: "",
email: "",
password: "",
confirmPassword: "",
});
const [codeSent, setCodeSent] = useState(false);
const [confirmed, setConfirmed] = useState(false);
const [isConfirming, setIsConfirming] = useState(false);
const [isSendingCode, setIsSendingCode] = useState(false);
function validateCodeForm() {
return fields.email.length > 0;
}
function validateResetForm() {
return (
fields.code.length > 0 &&
fields.password.length > 0 &&
fields.password === fields.confirmPassword
);
}
async function handleSendCodeClick(event) {
event.preventDefault();
setIsSendingCode(true);
try {
await Auth.forgotPassword(fields.email);
setCodeSent(true);
} catch (error) {
onError(error);
setIsSendingCode(false);
}
}
async function handleConfirmClick(event) {
event.preventDefault();
setIsConfirming(true);
try {
await Auth.forgotPasswordSubmit(
fields.email,
fields.code,
fields.password
);
setConfirmed(true);
} catch (error) {
onError(error);
setIsConfirming(false);
}
}
function renderRequestCodeForm() {
return (
<form onSubmit={handleSendCodeClick}>
<FormGroup bsSize="large" controlId="email">
<FormLabel>Email</FormLabel>
<FormControl
autoFocus
type="email"
value={fields.email}
onChange={handleFieldChange}
/>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isSendingCode}
disabled={!validateCodeForm()}
>
인증 코드 보내기
</LoaderButton>
</form>
);
}
function renderConfirmationForm() {
return (
<form onSubmit={handleConfirmClick}>
<FormGroup bsSize="large" controlId="code">
<FormLabel>인증 코드</FormLabel>
<FormControl
autoFocus
type="tel"
value={fields.code}
onChange={handleFieldChange}
/>
<FormText>
이메일({fields.email})로 전송된 인증 코드를 확인해 주세요.
</FormText>
</FormGroup>
<hr />
<FormGroup bsSize="large" controlId="password">
<FormLabel>새 비밀번호</FormLabel>
<FormControl
type="password"
value={fields.password}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup bsSize="large" controlId="confirmPassword">
<FormLabel>비밀번호 확인</FormLabel>
<FormControl
type="password"
value={fields.confirmPassword}
onChange={handleFieldChange}
/>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isConfirming}
disabled={!validateResetForm()}
>
확인
</LoaderButton>
</form>
);
}
function renderSuccessMessage() {
return (
<div className="success">
<p><BsCheck size={16} /> 비밀번호가 재설정되었습니다.</p>
<p>
<Link to="/login">
새로운 비밀번호로 로그인하려면 여기를 클릭하세요.
</Link>
</p>
</div>
);
}
return (
<div className="ResetPassword">
{!codeSent
? renderRequestCodeForm()
: !confirmed
? renderConfirmationForm()
: renderSuccessMessage()}
</div>
);
}
여기서의 흐름을 간단히 살펴보겠습니다:
renderRequestCodeForm()
에서 사용자에게 계정의 이메일 주소를 입력하도록 요청합니다.- 사용자가 폼을 제출하면
Auth.forgotPassword(fields.email)
을 호출하여 프로세스를 시작합니다. 여기서Auth
는 AWS Amplify 라이브러리의 일부입니다. - 이렇게 하면 Cognito가 지정된 이메일 주소로 인증 코드를 보냅니다.
- 그런 다음 사용자가 Cognito에서 보낸 코드를 입력할 수 있는 폼을 보여줍니다. 이 폼은
renderConfirmationForm()
에서 렌더링되며, 사용자가 새 비밀번호를 입력할 수도 있습니다. - 사용자가 코드와 새 비밀번호를 입력하고 폼을 제출하면
Auth.forgotPasswordSubmit(fields.email, fields.code, fields.password)
를 호출합니다. 이렇게 하면 계정의 비밀번호가 재설정됩니다. - 마지막으로, 비밀번호가 성공적으로 재설정되었다는 메시지를 보여주고, 새로운 비밀번호로 로그인할 수 있는 로그인 페이지로 연결합니다.
몇 가지 스타일도 추가해 보겠습니다.
src/containers/ResetPassword.css
에 다음 내용을 추가합니다.
@media all and (min-width: 480px) {
.ResetPassword {
padding: 60px 0;
}
.ResetPassword form {
margin: 0 auto;
max-width: 320px;
}
.ResetPassword .success {
max-width: 400px;
}
}
.ResetPassword .success {
margin: 0 auto;
text-align: center;
}
.ResetPassword .success .glyphicon {
color: grey;
font-size: 30px;
margin-bottom: 30px;
}
라우트 추가하기
마지막으로, 이 부분을 앱의 나머지 부분과 연결해 보겠습니다.
src/Routes.js
에 라우트를 추가합니다.
<Route
path="/login/reset"
element={
<UnauthenticatedRoute>
<ResetPassword />
</UnauthenticatedRoute>
}
/>
그리고 헤더에서 해당 컴포넌트를 임포트합니다.
import ResetPassword from "./containers/ResetPassword";
로그인 페이지에서 링크 추가하기
이제 사용자가 로그인을 시도할 때 이 페이지로 이동할 수 있도록 해야 합니다.
src/containers/Login.js
에 링크를 추가해 보겠습니다. 로그인 버튼 위에 추가합니다.
<Link to="/login/reset">비밀번호를 잊으셨나요?</Link>
그리고 헤더에 Link
컴포넌트를 임포트합니다.
import { Link } from "react-router-dom";
마지막으로 src/containers/Login.css
에 다음 스타일을 추가하여 링크에 스타일을 적용합니다.
.Login form a {
margin-bottom: 15px;
display: block;
font-size: 14px;
}
이제 끝났습니다! 이제 /login/reset
로 이동하거나, 비밀번호를 재설정해야 할 때 로그인 페이지에서 이 링크를 통해 이동할 수 있습니다.
여기서 사용자는 이메일을 입력해 비밀번호를 재설정할 수 있습니다.
다음으로, 로그인한 사용자가 비밀번호를 변경하는 방법을 살펴보겠습니다.
For help and discussion
Comments on this chapter