Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/auth - 토큰 이슈 해결 #4

Merged
merged 2 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/common/passport/jwtStrategy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt');
const passport = require('passport');
const User = require('../../routes/user/user.model');
const config = require('../config'); // 비밀 키를 저장한 파일
const config = require('../config');

const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
Expand Down
75 changes: 46 additions & 29 deletions src/common/utils/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const jwt = require('jsonwebtoken');
const passport = require('passport');
const config = require('../config');

// JWT 토큰 생성 함수
exports.generateToken = (user) => {
return jwt.sign(
{
Expand All @@ -14,44 +15,60 @@ exports.generateToken = (user) => {
);
};

// JWT 토큰 검증 함수
exports.verifyToken = (token) => {
return jwt.verify(token, config.jwtSecret);
};

exports.isAuthenticated = (req, res, next) => {
passport.authenticate('jwt', { session: false }, (err, user, info) => {
if (err) {
return res.status(500).json({ message: '서버 오류' });
}
if (!user) {
return res.status(401).json({ message: '인증되지 않은 사용자' });
}
req.user = user;
next();
})(req, res, next);
// JWT 인증 함수
const authenticateJWT = (req, res) => {
return new Promise((resolve, reject) => {
passport.authenticate('jwt', { session: false }, (err, user, info) => {
if (err) {
return reject({ status: 500, message: '서버 오류', error: err.message });
}
if (info) {
switch (info.name) {
case 'TokenExpiredError':
return reject({ status: 401, message: '토큰이 만료되었습니다.', expiredAt: info.expiredAt });
case 'JsonWebTokenError':
return reject({ status: 401, message: '유효하지 않은 토큰입니다.' });
default:
return reject({ status: 401, message: '인증되지 않은 사용자' });
}
}
if (!user) {
return reject({ status: 401, message: '로그인이 필요합니다.' });
}
resolve(user);
})(req, res);
});
};

exports.isLoggedIn = (req, res, next) => {
passport.authenticate('jwt', { session: false }, (err, user, info) => {
if (err) {
return res.status(500).json({ message: '서버 오류' });
}
if (!user) {
return res.status(401).json({ message: '로그인이 필요합니다.' });
}
// 로그인 여부 확인 미들웨어
exports.isLoggedIn = async (req, res, next) => {
try {
const user = await authenticateJWT(req, res);
req.user = user;
next();
})(req, res, next);
} catch (error) {
res.status(error.status).json({
message: error.message,
...(error.expiredAt && { expiredAt: error.expiredAt }),
});
}
};

exports.isNotLoggedIn = (req, res, next) => {
passport.authenticate('jwt', { session: false }, (err, user, info) => {
if (err) {
return res.status(500).json({ message: '서버 오류' });
// 비로그인 여부 확인 미들웨어
exports.isNotLoggedIn = async (req, res, next) => {
try {
await authenticateJWT(req, res);
res.status(403).json({ message: '이미 로그인된 상태입니다.' });
} catch (error) {
if (error.status === 401) {
next();
} else {
res.status(error.status).json({ message: error.message });
}
if (user) {
return res.status(403).json({ message: '이미 로그인된 상태입니다.' });
}
next();
})(req, res, next);
}
};
64 changes: 38 additions & 26 deletions src/common/utils/kakao.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,49 @@
const axios = require('axios');
const conf = require('../../common/config');

const header = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: 'Bearer ',
};
exports.getKakaoToken = async (code) => {
const data = {
grant_type: 'authorization_code',
client_id: conf.kakaoRestApiKey,
code,
};
try {
const header = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: 'Bearer ',
};
const data = {
grant_type: 'authorization_code',
client_id: conf.kakaoRestApiKey,
code,
};

const queryString = Object.keys(data)
.map((k) => encodeURIComponent(k) + '=' + encodeURIComponent(data[k]))
.join('&');
const queryString = Object.keys(data)
.map((k) => encodeURIComponent(k) + '=' + encodeURIComponent(data[k]))
.join('&');

const token = await axios.post('https://kauth.kakao.com/oauth/token', queryString, { headers: header });
return { accessToken: token.data.access_token };
const token = await axios.post('https://kauth.kakao.com/oauth/token', queryString, { headers: header });
return { accessToken: token.data.access_token };
} catch (err) {
console.log(err);
}
};
exports.getUserInfo = async (accessToken) => {
// Authorization: 'Bearer access_token'
header.Authorization += accessToken;
try {
const header = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: 'Bearer ',
};
// Authorization: 'Bearer access_token'
header.Authorization += accessToken;

// 카카오 사용자 정보 조회
const get = await axios.get('https://kapi.kakao.com/v2/user/me', { headers: header });
const result = get.data;
// 카카오 사용자 정보 조회
const get = await axios.get('https://kapi.kakao.com/v2/user/me', { headers: header });
const result = get.data;

return {
snsId: result.id,
email: result.kakao_account.email ? result.kakao_account.email : `${result.id}@no.agreement`,
// NOTE: 닉네임 10글자 제한 때문에, 임시 처리
// kakao 닉네임 규정은 20글자. result.id는 10글자로 추정
nickname: result.id,
};
return {
snsId: result.id,
email: result.kakao_account.email ? result.kakao_account.email : `${result.id}@no.agreement`,
// NOTE: 닉네임 10글자 제한 때문에, 임시 처리
// kakao 닉네임 규정은 20글자. result.id는 10글자로 추정
nickname: result.id,
};
} catch (err) {
console.log(err);
}
};