사용자 이메일 변경 기능 추가하기
사용자가 이메일을 변경할 수 있도록 허용하기
우리는 Serverless 노트 앱의 사용자들이 이메일을 변경할 수 있도록 하고 싶습니다. 우리는 사용자 관리를 위해 Cognito를 사용하고 있으며, React 앱에서 AWS Amplify를 사용하고 있습니다. 이번 장에서는 이를 어떻게 구현할지 살펴보겠습니다.
참고로, 우리는 다음과 같은 포크된 버전의 노트 앱을 사용하고 있습니다:
- 별도의 GitHub 저장소: https://github.com/AnomalyInnovations/serverless-stack-demo-user-mgmt-client
- 그리고 이 앱은 https://demo-user-mgmt.sst.dev를 통해 접근할 수 있습니다.
이전 장에서 /settings/email
로 연결되는 설정 페이지를 만들었습니다. 이제 이를 구현해 보겠습니다.
이메일 변경 폼
src/containers/ChangeEmail.js
에 다음 내용을 추가합니다.
import React, { useState } from "react";
import { Auth } from "aws-amplify";
import { useNavigate } from "react-router-dom";
import {
FormText,
FormGroup,
FormControl,
FormLabel,
} from "react-bootstrap";
import LoaderButton from "../components/LoaderButton";
import { useFormFields } from "../lib/hooksLib";
import { onError } from "../lib/errorLib";
import "./ChangeEmail.css";
export default function ChangeEmail() {
const nav = useNavigate();
const [codeSent, setCodeSent] = useState(false);
const [fields, handleFieldChange] = useFormFields({
code: "",
email: "",
});
const [isConfirming, setIsConfirming] = useState(false);
const [isSendingCode, setIsSendingCode] = useState(false);
function validateEmailForm() {
return fields.email.length > 0;
}
function validateConfirmForm() {
return fields.code.length > 0;
}
async function handleUpdateClick(event) {
event.preventDefault();
setIsSendingCode(true);
try {
const user = await Auth.currentAuthenticatedUser();
await Auth.updateUserAttributes(user, { email: fields.email });
setCodeSent(true);
} catch (error) {
onError(error);
setIsSendingCode(false);
}
}
async function handleConfirmClick(event) {
event.preventDefault();
setIsConfirming(true);
try {
await Auth.verifyCurrentUserAttributeSubmit("email", fields.code);
nav("/settings");
} catch (error) {
onError(error);
setIsConfirming(false);
}
}
function renderUpdateForm() {
return (
<form onSubmit={handleUpdateClick}>
<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={!validateEmailForm()}
>
Update Email
</LoaderButton>
</form>
);
}
function renderConfirmationForm() {
return (
<form onSubmit={handleConfirmClick}>
<FormGroup bsSize="large" controlId="code">
<FormLabel>Confirmation Code</FormLabel>
<FormControl
autoFocus
type="tel"
value={fields.code}
onChange={handleFieldChange}
/>
<FormText>
Please check your email ({fields.email}) for the confirmation code.
</FormText>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isConfirming}
disabled={!validateConfirmForm()}
>
Confirm
</LoaderButton>
</form>
);
}
return (
<div className="ChangeEmail">
{!codeSent ? renderUpdateForm() : renderConfirmationForm()}
</div>
);
}
사용자 이메일 변경 흐름은 사용자 가입 방식과 매우 유사합니다.
- 사용자에게 새 이메일을 입력하도록 요청합니다.
- Cognito가 사용자에게 인증 코드를 보냅니다.
- 사용자가 코드를 입력하면 이메일 변경이 확인됩니다.
먼저 renderUpdateForm()
에서 사용자에게 새 이메일을 입력하도록 요청하는 폼을 렌더링합니다. 사용자가 이 폼을 제출하면 다음을 호출합니다.
const user = await Auth.currentAuthenticatedUser();
Auth.updateUserAttributes(user, { email: fields.email });
이 코드는 현재 사용자를 가져와 Amplify의 Auth
모듈을 사용해 이메일을 업데이트합니다. 그런 다음 renderConfirmationForm()
에서 코드를 입력할 수 있는 폼을 렌더링합니다. 이 폼을 제출하면 다음을 호출합니다.
Auth.verifyCurrentUserAttributeSubmit("email", fields.code);
이 코드는 Cognito 측에서 변경 사항을 확인합니다. 마지막으로 사용자를 설정 페이지로 리디렉션합니다.
src/containers/ChangeEmail.css
에 몇 가지 스타일을 추가합니다.
@media all and (min-width: 480px) {
.ChangeEmail {
padding: 60px 0;
}
.ChangeEmail form {
margin: 0 auto;
max-width: 320px;
}
}
마지막으로 src/Routes.js
에 새 페이지를 추가합니다.
<AuthenticatedRoute exact path="/settings/email">
<ChangeEmail />
</AuthenticatedRoute>
그리고 헤더에서 이를 임포트합니다.
import ChangeEmail from "./containers/ChangeEmail";
이제 사용자가 이메일을 변경할 수 있습니다.
세부 사항
사용자가 새 이메일을 확인하지 않으면 이메일 변경 흐름이 중단될 수 있습니다. 이 경우 이메일이 변경된 것처럼 보이지만 Cognito는 이를 확인되지 않은 상태로 표시합니다. 이 경우를 여러분이 직접 처리하도록 하겠지만, 이를 수행하는 방법에 대한 몇 가지 힌트를 제공합니다.
-
Auth.userAttributes(currentUser)
를 호출하여 현재 사용자의 Cognito 속성을 가져올 수 있습니다. 이메일 속성을 찾고attributes["email_verified"] !== "false"
를 사용하여 확인되지 않았는지 확인합니다. -
이 경우 사용자가 확인 코드를 다시 보낼 수 있는 간단한 표시를 보여줍니다.
Auth.verifyCurrentUserAttribute("email")
을 호출하여 이를 수행할 수 있습니다. -
다음으로 위의 확인 코드 폼을 표시하고
Auth.verifyCurrentUserAttributeSubmit("email", fields.code)
를 호출하여 동일한 흐름을 따를 수 있습니다.
이렇게 하면 이메일 변경 흐름이 더 견고해지고 사용자가 새 이메일을 확인하는 것을 잊은 경우를 처리할 수 있습니다.
For help and discussion
Comments on this chapter