회원가입 CRUD와 로그인 구현을 끝내고
passport
를 했다.passport
는 Node.js용 미들 인증웨어이다. 그동안 회원 가입을 구현하면서 백으로 api만 만들다가 실제로 사용되고 있는 sns 로그인을 구현하고자 하니까 신기했다.
신청 과정은 검색하면 워낙 잘 설명 되어 있는 정보가 넘쳐나기 때문에 생략.
하지만 아래의 두 가지는 확실히 해야 한다.
사이트 도메인
: http://localhost:3000
Redirect URI
: http://localhost:3000/api/auth/kakao/callback
나는 여기서 RESP API
키를 사용 할 것이다.
환경 변수로 지정 해준다.
카카오 로그인은 로그인 인증 과정을 카카오에게 맡긴다.
사용자는 번거롭게 새로운 사이트에 회원가입을 매번 할 필요가 없어지고, 서비스 제공자는 로그인 과정을 검증된 SNS에 맡길 수 있어 편리하다.
SNS 로그인의 특징은 회원가입의 절차가 따로 없다.
카카오로 예시를 들 경우, 로그인만 하면, 따로 회원가입 절차 없이 사이트에 로그인 할 수 있는걸 봤을 것이다.
passport-kakao 설치
yarn add express-session passport passport-kakao
/app.js
import express from "express"; import session from "express-session"; import passport from "passport" . . . // 세션 app.use( session({ secret: process.env.SECRET_KEY, resave: false, saveUninitialized: false, cookie: { secure: false }, }), ); app.use(passport.initialize()); app.use(passport.session()); //시리얼라이즈 passport.serializeUser((user, done) => { done(null, user.id); }); //디시리얼라이즈 passport.deserializeUser(async (id, done) => { try { const user = await Users.findByPk(id); done(null, user); } catch (error) { console.log(error); done(error); } }); . . . app.get('/', (req, res) => { res.send("서버가 켜졌습니다"); });
./routers/auth.js
import {Router} from "express"; import passport from "passport"; const authRouter = Router(); . . . // 카카오 로그인 API authRouter.get("/kakao", passport.authenticate("kakao")); authRouter.get( "/kakao/callback", passport.authenticate("kakao", { failureRedirect: "/?error=카카오로그인 실패", }), (req, res) => { res.status(200).redirect("/"); // 성공 시에는 /로 이동 }, );
./passport/kakaoStrategy.js
import passport from "passport"; import { Strategy as KakaoStrategy } from "passport-kakao"; import db from "../models/index.js"; const { Users } = db; const kakaostrategy = () => { passport.use( "kakao", new KakaoStrategy( { clientID: process.env.KAKAO_ID, callbackURL: "http://localhost:3000/api/auth/kakao/callback", }, async (accessToken, refreshToken, profile, done) => { console.log("kakao profile", profile); try { const exUser = await Users.findOne({ // users db의 email중 `해당 이메일과 일치 하는 경우` where: { email: `kakao${profile._json.id}@kakao.com` }, }); // 이미 가입된 카카오 프로필이면 성공 if (exUser) { console.log("가입 이력 있음", accessToken); done(null, exUser); } else { // 가입되지 않는 유저면 회원가입 시키고 로그인을 시킨다. const newUser = await Users.create({ email: `kakao${profile.id}@kakao.com`, nickName: profile.displayName, imgUrl: profile._json.properties.profile_image, password: profile.id, refreshToken: refreshToken, type: "kakao", }); console.log("가입 이력 없음", accessToken); done(null, newUser); } } catch (error) { console.error(error); done(error); } }, ), ); }; export { kakaostrategy };
./routers/index.js
import { Router } from "express"; import { userRouter } from "./users.router.js"; import { authRouter } from "./auth.router.js"; import passport from "passport"; // 카카오 strategy import import { kakaostrategy } from "../passport/kakaoStrategy.js"; const apiRouter = Router(); apiRouter.use("/user", userRouter); // kakaostrategy 미들웨어 실행 kakaostrategy(); apiRouter.use("/auth", authRouter); export { apiRouter };
데이터가 잘 들어왔다.