โ ๋ฒ๊ทธ๋ณด๊ณ ๋๋๊ฐ์ด ์คํ๋ณด๊ณ ๋๋๋ค. โ
- ๊ฐ๋ฐ์ ์๋ด(Programmerโs Proverbs)

๊ตฌ๊ธ ๋ก๊ทธ์ธ OAuth ์ ์ฒญ
์ฐ์ https://console.developers.google.com/apis ์ ์ ์ํด์ client ID์ client secret๋ฅผ ๋ฐ๊ธ๋ฐ์์ผ ํ๋ค.
Google Cloud Platform
ํ๋์ ๊ณ์ ์ผ๋ก ๋ชจ๋ Google ์๋น์ค๋ฅผ Google Cloud Platform์ ์ฌ์ฉํ๋ ค๋ฉด ๋ก๊ทธ์ธํ์ธ์.
accounts.google.com
1. ์ ํ๋ก์ ํธ ์์ฑ

2. OAuth ๋์ ํ๋ฉด ๊ตฌ์ฑ
๊ตฌ๊ธ ๋ก๊ทธ์ธํ ๋, ์๋น์ค ๋์ ํ๋ฉด์ ์ด๋ค ์ ๋ณด๋ฅผ ๋์ธ์ง ๊ตฌ์ฑํ๋ค.




๊ฐ๊ฐ ์ ๋ณด๋ฅผ ๊ธฐ์ ํ๊ณ , ์ ์ฅํ ๊ณ์ ๋ฒํผ์ ๋๋ฅธ๋ค.
3. SCOPE ์ ๋ณด ์ค์


4. OAuth ํด๋ผ์ด์ธํธ ID ์์ฑ


5. ํ ์คํธ ์ฌ์ฉ์ ์์ฑ

6. ํด๋ผ์ด์ธํธ ์์ด๋/๋น๋ฐ๋ฒํธ ๋ฐ๊ธ
์์ฑ๋ ํด๋ผ์ด์ธํธ ID์ ๋ณด์ ๋น๋ฐ๋ฒํธ๋ฅผ ๊ฐ๊ฐ ๋ณต์ฌํด๋๋ค.

๊ตฌ๊ธ ๋ก๊ทธ์ธ ๋ผ์ฐํฐ ์ ๋ต ๊ตฌํ

passport-google-oauth20
passport oauth2 ์ google ๋ก๊ทธ์ธ ์ฐ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ค๋ค.
$ npm install passport-google-oauth20
passport-google-oauth20
Google (OAuth 2.0) authentication strategy for Passport.
www.passportjs.org
๋ชจ๋์ ์ค์นํ๋ค๋ฉด, .env ํ์ผ์ ์์์ ๋ฐ๊ธํ client id์ ๋น๋ฐ๋ฒํธ๋ฅผ ํ๊ฒฝ๋ณ์ ๋ฑ๋ก์ ํด์ค๋ค.

routes/auth.js
- naver OAuth๊ฒฝ๋ก ์ค์
//* ๊ตฌ๊ธ๋ก ๋ก๊ทธ์ธํ๊ธฐ ๋ผ์ฐํฐ ***********************
router.get('/google', passport.authenticate('google', { scope: ['profile', 'email'] })); // ํ๋กํ์ผ๊ณผ ์ด๋ฉ์ผ ์ ๋ณด๋ฅผ ๋ฐ๋๋ค.
//? ์์์ ๊ตฌ๊ธ ์๋ฒ ๋ก๊ทธ์ธ์ด ๋๋ฉด, ๋ค์ด๋ฒ redirect url ์ค์ ์ ๋ฐ๋ผ ์ด์ชฝ ๋ผ์ฐํฐ๋ก ์ค๊ฒ ๋๋ค. ์ธ์ฆ ์ฝ๋๋ฅผ ๋ฐ๊ฒ๋จ
router.get(
'/google/callback',
passport.authenticate('google', { failureRedirect: '/' }), //? ๊ทธ๋ฆฌ๊ณ passport ๋ก๊ทธ์ธ ์ ๋ต์ ์ํด googleStrategy๋ก ๊ฐ์ ๊ตฌ๊ธ๊ณ์ ์ ๋ณด์ DB๋ฅผ ๋น๊ตํด์ ํ์๊ฐ์
์ํค๊ฑฐ๋ ๋ก๊ทธ์ธ ์ฒ๋ฆฌํ๊ฒ ํ๋ค.
(req, res) => {
res.redirect('/');
},
);
passport/googleStrategy.js
- ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ ๋ต
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const User = require('../models/user');
module.exports = () => {
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_ID, // ๊ตฌ๊ธ ๋ก๊ทธ์ธ์์ ๋ฐ๊ธ๋ฐ์ REST API ํค
clientSecret: process.env.GOOGLE_SECRET,
callbackURL: '/auth/google/callback', // ๊ตฌ๊ธ ๋ก๊ทธ์ธ Redirect URI ๊ฒฝ๋ก
},
async (accessToken, refreshToken, profile, done) => {
console.log('google profile : ', profile);
try {
const exUser = await User.findOne({
// ๊ตฌ๊ธ ํ๋ซํผ์์ ๋ก๊ทธ์ธ ํ๊ณ & snsIdํ๋์ ๊ตฌ๊ธ ์์ด๋๊ฐ ์ผ์นํ ๊ฒฝ์ฐ
where: { snsId: profile.id, provider: 'google' },
});
// ์ด๋ฏธ ๊ฐ์
๋ ๊ตฌ๊ธ ํ๋กํ์ด๋ฉด ์ฑ๊ณต
if (exUser) {
done(null, exUser); // ๋ก๊ทธ์ธ ์ธ์ฆ ์๋ฃ
} else {
// ๊ฐ์
๋์ง ์๋ ์ ์ ๋ฉด ํ์๊ฐ์
์ํค๊ณ ๋ก๊ทธ์ธ์ ์ํจ๋ค
const newUser = await User.create({
email: profile?.email[0].value,
nick: profile.displayName,
snsId: profile.id,
provider: 'google',
});
done(null, newUser); // ํ์๊ฐ์
ํ๊ณ ๋ก๊ทธ์ธ ์ธ์ฆ ์๋ฃ
}
} catch (error) {
console.error(error);
done(error);
}
},
),
);
};
passport/index.js
- googleStrategy.js ๋ฑ๋ก
const passport = require('passport');
const local = require('./localStrategy'); // ๋ก์ปฌ์๋ฒ๋ก ๋ก๊ทธ์ธํ ๋
const google = require('./googleStrategy'); // ๊ตฌ๊ธ์๋ฒ๋ก ๋ก๊ทธ์ธํ ๋
const User = require('../models/user');
module.exports = () => {
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findOne({ where: { id } })
.then(user => done(null, user))
.catch(err => done(err));
});
local();
google(); // ๊ตฌ๊ธ ์ ๋ต ๋ฑ๋ก
};
๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ธ์ฆ ์์
- google ๋ก๊ทธ์ธ ํด๋ฆญ
- router.get('/auth/google) ์ผ๋ก requestrk ์ด
- passport.use์์ new GoogleStrategy ์คํ cliendID, clientSecret ์ธ์ฆ์ฑ๊ณต
- ๊ตฌ๊ธ์ด๋ ๋ฐ ์ฌ์ฉ์ ์ ๋ณด ๊ถํ ์น์ธ
- ๊ตฌ๊ธ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ callbackํด์ค
- passport.use์์ function(accessToken, refreshToken, profile, done)์์ callback ๋ฐ์ ์ฌ์ฉ์ ์ ๋ณด(profile)๋ฅผ ๋ฐ์
- ๊ทธ ์ดํ์ DB ์ฒ๋ฆฌ๋ฅผ ํตํด ์ ์ ๋ฅผ ๋ก๊ทธ์ธ ๋ก์ง์ ์คํ ํ๊ณ done๋ฅผ return ํด์ฃผ์ด ๋ผ์ฐํฐ๋ก ๋์์ด
์ด ๊ธ์ด ์ข์ผ์ จ๋ค๋ฉด ๊ตฌ๋ & ์ข์์
์ฌ๋ฌ๋ถ์ ๊ตฌ๋
๊ณผ ์ข์์๋
์ ์์๊ฒ ํฐ ํ์ด ๋ฉ๋๋ค.