2024. 2. 13. 21:52ㆍ공부/내배캠 TIL
목차
1. 문제
회원가입 라우터는 email, password, password_check, name, interest를 포함하는 body를 post하고,
email이 db에 이미 존재하는지, password와 password_check가 같은지, password의 길이가 6 이상인지 확인한 뒤
이메일을 bcrypt를 사용해 암호화한 뒤 email, (암호화된)password, name, interest를 저장하는 것으로 구현하였다.
2. 시도
1. 설치
npm i nodemailer
2. google 계정 준비
[NodeJS] nodemailer로 이메일 보내기 (tistory.com)
해당 링크의 [2단계 인증 해결 방법] 부분을 참고하였다.
2단계 인증이 완료된 google 계정에서 [앱 비밀번호]를 발급받아 .env에 추가해주었다.
# Gamil_2
GMAIL_USER = "이메일"
GAMIL_APP_PW = "앱 비밀번호"
3. Nodemailer를 사용하여 이메일 서버의 환경을 설정해준다.
import nodemailer from 'nodemailer';
import dotenv from 'dotenv';
dotenv.config();
const { GMAIL_USER, GAMIL_APP_PW } = process.env;
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: GMAIL_USER,
pass: GAMIL_APP_PW,
},
});
export default function emailSender(toEmail, Token) {
const mailOptions = {
from: GMAIL_USER,
to: toEmail,
subject: '우리동네 동아리(우동) 회원가입 인증',
html: `<p>아래의 주소를 클릭하여 이메일을 인증해 주세요 : </p>
<p> <a href="http://localhost:3000/api/auth?email=${toEmail}&token=${Token}">인증하기</a></p>`,
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.error(error);
} else {
console.log('Email Sent : ', info);
}
});
}
먼저 nodemailer를 사용하여 email을 보내줄 transporter를 생성해준다.
mailOptions에서는 발송될 객체를 작성한다.
-> href를 생성하는 것도 함수화 했다면 더 좋았을지도 모르겠다.
4. 이메일 발송 api 작성
router.post('/email', async (req, res, next) => {
const { email } = req.body;
const user = await prisma.users.findUnique({ where: { email } });
if (!user.isVerified) {
const verifyToken = createVerifyToken(user.email);
res.cookie('verification', `Bearer ${verifyToken}`);
await emailSender(email, verifyToken);
try {
res.json({
ok: true,
msg: '이메일이 성공적으로 전송되었습니다.',
token: verifyToken,
});
} catch (error) {
console.error('이메일 전송에 실패했습니다:', error);
res.status(500).json({ ok: false, msg: '이메일 전송에 실패했습니다.' });
}
} else {
res.status(400).json({ ok: false, msg: '이미 인증 완료된 이메일입니다.' });
}
});
유저의 인증 상태를 검증하고(isVerified) 조건을 만족한다면 verifyToken을 생성하고, 해당 토큰과 email을 입력받아
emailSender로 전송을 시도한다.
5. 이메일 인증 api 작성
import express from 'express';
import { prisma } from '../utils/index.js';
import jwt from 'jsonwebtoken';
const router = express.Router();
router.get('/auth', async (req, res) => {
const email = req.query.email;
const token = req.query.token;
try {
const decodedToken = jwt.verify(token, process.env.CUSTOM_SECRET_KEY);
if (decodedToken.email === email) {
const updatedVerify = await prisma.users.update({
where: { email: email },
data: {
isVerified: true,
},
});
return res.status(200).json({
message: 'Email 인증 처리 완료.',
user: updatedVerify,
});
} else {
res.status(400).send('부적절한 email 또는 token.');
}
} catch (error) {
console.error('토큰 인증 오류:', error);
res.status(500).send('토큰 인증 오류.');
}
});
export default router;
전송된 email과 verifyToken에서 email과 Token을 복호화 했을때 나오는 email을 비교하여 둘이 같다면 isVerified(default는 false)를 true로 바꿔주는 방식을 사용했다.
3. 결과
4. 배운점
nodemailer를 사용하여 이메일을 보내고, email로 받은 링크를 통해 email 인증을 구현하는 방법을 알 수 있었습니다.
이메일과 토큰을 그대로 url에 포함시키는 상황이라, 걱정되기는 하지만, bcrty등의 암호화를 사용하면 보안성을 향상시킬 수 있을 것이라 생각합니다.
'공부 > 내배캠 TIL' 카테고리의 다른 글
[Node.js_4기] Today_I_Learn : 객체지향 (24/02/16) (0) | 2024.02.16 |
---|---|
[Node.js_4기] TIL : 뉴스피드 프로젝트 회고 (24/02/14) (1) | 2024.02.15 |
[Node.js_4기] TIL : Refresh Token 토막글 (24/02/08) (1) | 2024.02.08 |
[Node.js_4기] TIL : 뉴스피드 프로젝트 (24/02/07) (3) | 2024.02.08 |
[Node.js_4기] TIL - 개인과제 정렬기능 리팩토링(24/02/05) (0) | 2024.02.05 |