๐๏ธ ์ํฉ
๋๋ ์ฌ์ค ์์ฃผ ์์ ๋ถํฐ
์นด์นด์คํก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ณผ ๊ฐ์ ์์ ๋ก๊ทธ์ธ๊ธฐ๋ฅ์ ๊ผญ ํด๋ณด๊ณ ์ถ์๋ค.
์ฌ์ฉ์๋ก์๋ ๋๋ฌด ํธ๋ฆฌํ ๊ธฐ๋ฅ์ด์๊ณ ,
์์ผ๋ก๋ ๋ง์ด ๊ตฌํํ๊ฒ ๋ ๊ธฐ๋ฅ ๊ฐ์ ํ์์ ์ด๋ผ๊ณ ์๊ฐํ๋ค.
๋ฌผ๋ก ๊ทธ ์ ์ ๊ธฐ์ด์ ์ธ ์ฟ ํค, ํ ํฐ, ์ธ์ , refreshToken ๋ฑ๋ฑ์ ์์์ผ ํ์ง๋ง,
์ฝ๋ฉ์ ์ฒ์ ์์ํ๋ ๊ทธ๋์๋ ๊ฒ์ด ์์๊ณ , ์ผ๋จ ์ฌ์ดํธ์์ ๋ค์ ธ๋ดค์๋ค.
ํ์ง๋ง ๊ทธ ๋น์์๋ ๊ธฐ์ด์ง์์ด ๋ถ์กฑํด ์ ์์๋ฃ์ง ๋ชปํ๊ณ , ๊ฒฐ๊ตญ ๋ชปํ๋ค.
๋ถํธ์บ ํ๋ฅผ ํตํด ๊ณต๋ถํ๋ฉด์, ์ธ์ฆ ์ธ๊ฐ์ ๊ฐ์ ๊ฐ๋ ๋ค์ ๋ฐฐ์ฐ๊ณ ๋๋,
์ด์ ์ง์ง ํ ์ ์์ ๊ฒ ๊ฐ์๋ค.
๊ทธ๋์ ํํ๋ก์ ํธ ํ์๊ธฐ๋ฅ์ ๋ชจ๋ ๊ตฌํ์ ํ ๋ค์,
๋ฐค์ ์๋ฉด์๋ผ๋ ๊ตฌํ์ ํด์ผ๊ฒ ๋ค ๋ง์ ๋จน์๋ค.
์ผ๋จ ์ง๊ธ๊น์ง ์ ๋ฆฌ๋ ๋ด์ฉ์ ์ ์ด๋ณด๊ฒ ๋ค.
๊ณต๋ถ๋ ์ํ์ฝ๋ฉ๋ ๊ฐ์์,
์ธํ๋ ๋ธ๋ก๊ทธ ๋ฐ ๋ค๋ฅธ ๋ง์ ๋ธ๋ก๊ทธ๋ฅผ ๋ณด์๋ค.
๐ฃ passport
- ์ธ์ฆ ๋ฐ ์ธ๊ฐ ์์ ์ ์์ด์ ์ข๋ ํธ๋ฆฌํ๊ฒ ๊ฐ๋ฐํ ์ ์๋๋ก ๋์์ฃผ๋ ๋ชจ๋์ด๋ค.
- ์์ ๋ก๊ทธ์ธ์ ๊ตฌํํ ๋ ๋ง์ด ์ฌ์ฉ๋๋ค.
- passport ์๋ 2๊ฐ์ง ์ข ๋ฅ๊ฐ ์๋ค๊ณ ๋ณด๋ฉด ๋๋ค. ๋ก์ปฌ ๋ฐฉ์, ์์ ๋ก๊ทธ์ธ ๋ฐฉ์.
๋์ ๊ฒฝ์ฐ ์์ ๋ก๊ทธ์ธ์ ์ํด passport๋ฅผ ๋์ ํ ๊ฒ์์ผ๋ก, ๋ก์ปฌ๋ฐฉ์์ ์ง๋๊ฐ๊ฒ ๋ค.
์ผ๋จ 4๊ฐ์ ํ์ผ์ ๋ง๋ค์๋ค. ๊ทธ๋ฆฌ๊ณ ๊ธฐ์กด์ ์๋ app.js ํ์ผ์๋ ์ฝ๋๋ค์ ์ถ๊ฐํ๋ค.
์ผ๋จ app.js์ ์ถ๊ฐํ ์ฝ๋๋ ์๋์ ๊ฐ๋ค.
const passport = require('passport');
const kakaoStrategy = require('passport-kakao').Strategy;
const passportConfig = require('./passport');
const session = require('express-session');
passportConfig();
app.use(
session({
resave: false,
satisfies: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
}),
);
app.use(passport.initialize()); //req์ passport์ค์ ์ฌ์.
app.use(passport.session()); //req์ passport ์ ๋ณด ์ ์ฅ.
app.use('/api', [
authRouter,
UsersRouter,
PostsRouter,
CommentsRouter,
]);
์นด์นด์ค ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๋ฃ๊ธฐ ์ํด ๋ง๋ค์๋ ํ์ผ์ ์๋์ ๊ฐ๋ค.
passport ๋ผ๋ ํ์ผ ์์
index.js
kakaoStrategy.js
routers ํ์ผ ์์
auth.js
์ผ๋จ routers/auth.js ํ์ผ ๋จผ์ ๋ณด๊ฒ ๋ค.
require('dotenv').config();
const express = require('express');
const passport = require('passport');
const router = express.Router();
const jwt = require('jsonwebtoken');
//์ด ์ฃผ์๋ก ์์ฒญ์ด ๋ค์ด์ค๋ฉด authenticate ํจ์๋ฅผ ํธ์ถํ๋ค.
//๊ทธ๋ผ kakaoStrategy๋ก ์ด๋ํด ์ ๋ต์ ์คํํ๋ค.
//์นด์นด์ค ๋ก๊ทธ์ธ์์๋ ์นด์นด์ค ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋ํ๋ค.
router.get('/kakao', passport.authenticate('kakao'));
//์นด์นด์ค ๋ก๊ทธ์ธ ํ์ด์ง์์ ๋ก๊ทธ์ธ ๋ฒํผ์ ๋๋ฅด๋ฉด ์นด์นด์ค์์ ์ค์ ํ redirect uri๋ก ์ด๋ํ๋ค.
router.get(
'/kakao/callback',
passport.authenticate('kakao', {
//ํธ์ถ์ ๊ฒฐ๊ณผ๊ฐ ์คํจ๋ผ๋ฉด ์๋์ ๊ฒฝ๋ก๋ก ๋ฆฌ๋ค์ด๋ ํธ ํ๋ค.
failureRedirect: '/api/login',
}),
//ํธ์ถ์ ๊ฒฐ๊ณผ๊ฐ ์ฑ๊ณต์ด๋ผ๋ฉด ์๋ ์ผ๋ จ์ ๊ณผ์ ์ ์ฒ๋ฆฌํ๋ค.
async (req, res) => {
const userId = req.user.dataValues.id;
const token = jwt.sign(
{ userId: userId },
process.env.SECRET_KEY,
{
expiresIn: '12h',
},
);
res.cookie('Authorization', `Bearer ${token}`);
res.locals.user = { userId: req.user.dataValues.id };
res.redirect('/api/main');
},
);
module.exports = router;
๋ค์์ผ๋ก authenticate๊ฐ ํธ์ถ๋๋ฉด์ ์คํ๋๋
kakaoStrategy.js ํ์ผ์ ์ดํด๋ณด๊ฒ ๋ค.
require('dotenv').config();
const passport = require('passport');
const kakaoStrategy = require('passport-kakao').Strategy;
const bcrypt = require('bcrypt');
const { Users } = require('../models');
const kakaoLogin = () => {
passport.use(
new kakaoStrategy(
{
clientID: process.env.KAKAO_ID,
callbackURL: '/api/kakao/callback',
},
async (accessToken, refreshToken, profile, done) => {
try {
const exUser = await Users.findOne({
where: { email: profile._json.kakao_account.email },
});
const hashPwd = await bcrypt.hash('profile.id', 11);
//ํ์๊ฐ์
์ด ๋์ด์๋ ๊ฒฝ์ฐ
if (exUser) {
//์ด done์ด ์คํ๋๋ฉด์, routers/auth.js ํ์ผ์ authentication ๋ด๋ถ์ ์ฝ๋ฐฑํจ์๊ฐ ์คํ๋๋ค.
//๋ํ done() ํจ์์ ์ธ์๋ก ๋๊ธด ๊ฐ์ ๊ทธ๋๋ก ๋์ด๊ฐ ํ์ผ์์ ๋ฐ๋๋ค.
done(null, exUser);
} else {
//ํ์์ด ์๋๊ฒฝ์ฐ ํ์๊ฐ์
์ํค๊ธฐ
const newUser = await Users.create({
email: profile._json.kakao_account.email,
name: profile.displayName,
password: hashPwd, //์์
provider: 'kakao',
});
done(null, newUser);
}
} catch (err) {
//๊ทธ์ธ ์๋ฌ ๋ฐ์์ ์๋ฌ ์ ๋ฌ.
done(err);
}
},
),
);
};
module.exports = kakaoLogin;
์ธํ๋ ๋ธ๋ก๊ทธ๋ก ์๊ฒ๋ ์ฌ์ค์ธ๋ฐ, done ํจ์์ ์ธ์๊ฐ์ด ์๋์ ๊ฐ์ ์ญํ ์ ํ๋ค๋ ๊ฑธ ์๋ฉด ์ข๋ ์ดํด๊ฐ ์ฌ์ ๋ค.
//๋ก๊ทธ์ธ์ด ์ฑ๊ณตํ ๊ฒฝ์ฐ
done(null, exUser)
passport.authenticate('kakao', (authError, user, info)=>{})
//๋ก๊ทธ์ธ์ด ์คํจํ ๊ฒฝ์ฐ
done(null, false, [message: ])
passport.authenticate('kakao', (authError, user, info)=>{})
//์๋ฒ ์๋ฌ๋ ๊ฒฝ์ฐ
done(error)
passport.authenticate('kakao', (authError, user, info)=>{})
๋ค์์ passport/index.js ํ์ผ์ด๋ค.
const passport = require('passport');
const kakao = require('./kakaoStrategy.js');
const { Users } = require('../models');
module.exports = () => {
//req.session ๊ฐ์ฒด์ ๋ฐ์ดํฐ ์ ์ฅ.
passport.serializeUser((user, done) => {
done(null, user.id);
});
//์๋ฒ ์์ฒญ์ด ์ฌ๋๋ง๋ค ํญ์ด ์คํ๋๋ฉฐ, req.user์ ์ ์ฅํ๋ค.
passport.deserializeUser((id, done) => {
//์ ์ ์์ด๋๋ฅผ ํ
์ด๋ธ์์ ์ฐพ์ ๊ฒฝ์ฐ, ์ฑ๊ณตํ ๊ฒฝ์ฐ ๋ ํจ์ ์คํ.
Users.findOne({ where: { id } }).then(user => done(null, user));
});
kakao();
};
๐งก ๋๋์
์ด๋ฐ์์ผ๋ก ๋ธ๋ก๊ทธ๋ค์ ๋ฐ๋ผ๊ฐ๋ค ๋ณด๋
๋๋์ด ์นด์นด์คํก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ๊ตฌํ์ ์ฑ๊ณตํ์๋ค!!
๋๋ฌด ๊ธฐ๋ถ์ด ์ข์์ง๋ง, passport์ ๋ํด ์ ๋ง ์ ์๊ณ ์๋? ๋ผ๊ณ ๋ฌผ์ด๋ณธ๋ค๋ฉด ๋ ธ! ํ ๊บผ ๊ฐ๋ค..
์์ง์ ์ข๋ ๋ณด๊ณ , ๋ง์ ธ๋ด์ผ ๋ด๊ฒ์ผ๋ก ๋ง๋ค ์ ์์ ๊ฒ ๊ฐ๋ค.
์ด์จ๋ ๊ณผ์ ์ ์ถ ์ ์ ๊ตฌํํด์ ์ ๋ง ๋คํ์ด๋ค.