Showing
10 changed files
with
116 additions
and
13 deletions
| ... | @@ -117,4 +117,6 @@ dist | ... | @@ -117,4 +117,6 @@ dist |
| 117 | 117 | ||
| 118 | package-lock.json | 118 | package-lock.json |
| 119 | uploads | 119 | uploads |
| 120 | -static | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 120 | +static | ||
| 121 | +text | ||
| 122 | +*.txt | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | +import dotenv from "dotenv"; | ||
| 1 | import express from "express"; | 2 | import express from "express"; |
| 2 | import morgan from "morgan"; | 3 | import morgan from "morgan"; |
| 3 | import helmet from "helmet"; | 4 | import helmet from "helmet"; |
| ... | @@ -12,9 +13,9 @@ import routes from "./routes"; | ... | @@ -12,9 +13,9 @@ import routes from "./routes"; |
| 12 | import userRouter from "./routers/userRouter"; | 13 | import userRouter from "./routers/userRouter"; |
| 13 | import videoRouter from "./routers/videoRouter"; | 14 | import videoRouter from "./routers/videoRouter"; |
| 14 | import globalRouter from "./routers/globalRouter"; | 15 | import globalRouter from "./routers/globalRouter"; |
| 15 | - | ||
| 16 | import "./passport"; | 16 | import "./passport"; |
| 17 | 17 | ||
| 18 | +dotenv.config(); | ||
| 18 | const app = express(); | 19 | const app = express(); |
| 19 | 20 | ||
| 20 | const CokieStore = MongoStore(session); | 21 | const CokieStore = MongoStore(session); |
| ... | @@ -36,6 +37,7 @@ app.use( | ... | @@ -36,6 +37,7 @@ app.use( |
| 36 | store: new CokieStore({ mongooseConnection: mongoose.connection }), | 37 | store: new CokieStore({ mongooseConnection: mongoose.connection }), |
| 37 | }) | 38 | }) |
| 38 | ); | 39 | ); |
| 40 | + | ||
| 39 | app.use(passport.initialize()); | 41 | app.use(passport.initialize()); |
| 40 | app.use(passport.session()); | 42 | app.use(passport.session()); |
| 41 | 43 | ... | ... |
| ... | @@ -15,7 +15,7 @@ export const postJoin = async (req, res, next) => { | ... | @@ -15,7 +15,7 @@ export const postJoin = async (req, res, next) => { |
| 15 | res.render("join", { pageTitle: "Join" }); | 15 | res.render("join", { pageTitle: "Join" }); |
| 16 | } else { | 16 | } else { |
| 17 | try { | 17 | try { |
| 18 | - const user = await User.create({ | 18 | + const user = await User({ |
| 19 | name, | 19 | name, |
| 20 | email, | 20 | email, |
| 21 | }); | 21 | }); |
| ... | @@ -33,16 +33,57 @@ export const postJoin = async (req, res, next) => { | ... | @@ -33,16 +33,57 @@ export const postJoin = async (req, res, next) => { |
| 33 | 33 | ||
| 34 | export const getLogin = (req, res) => | 34 | export const getLogin = (req, res) => |
| 35 | res.render("login", { pageTitle: "Login" }); | 35 | res.render("login", { pageTitle: "Login" }); |
| 36 | + | ||
| 36 | export const postLogin = passport.authenticate("local", { | 37 | export const postLogin = passport.authenticate("local", { |
| 37 | failureRedirect: routes.login, | 38 | failureRedirect: routes.login, |
| 38 | successRedirect: routes.home, | 39 | successRedirect: routes.home, |
| 39 | }); | 40 | }); |
| 40 | 41 | ||
| 42 | +// 깃허브 로그인 | ||
| 43 | +export const githubLogin = passport.authenticate("github"); | ||
| 44 | +// call back 받아오는 함수 | ||
| 45 | +export const githubLoginCallback = async ( | ||
| 46 | + accessToken, | ||
| 47 | + refreshToken, | ||
| 48 | + profile, | ||
| 49 | + cb | ||
| 50 | +) => { | ||
| 51 | + // callback 정보 확인용 console.log | ||
| 52 | + // console.log(accessToken, refreshToken, profile, cb); | ||
| 53 | + const { | ||
| 54 | + _json: { id, avatar_url: avatarUrl, name, email }, | ||
| 55 | + } = profile; | ||
| 56 | + // profile 파라미터로 가져온 내용들 | ||
| 57 | + // 파라미터로 받은 cb함수가 처리해준다. True->정보를 쿠키에.. False->error | ||
| 58 | + try { | ||
| 59 | + const user = await User.findOne({ email }); | ||
| 60 | + if (user) { | ||
| 61 | + user.githubId = id; | ||
| 62 | + user.save(); | ||
| 63 | + return cb(null, user); | ||
| 64 | + } | ||
| 65 | + const newUser = await User.create({ | ||
| 66 | + email, | ||
| 67 | + name, | ||
| 68 | + githubId: id, | ||
| 69 | + avatarUrl, | ||
| 70 | + }); | ||
| 71 | + return cb(null, newUser); | ||
| 72 | + } catch (error) { | ||
| 73 | + return cb(error, null); | ||
| 74 | + } | ||
| 75 | +}; | ||
| 76 | + | ||
| 77 | +export const postGithubLogin = (req, res) => { | ||
| 78 | + res.redirect(routes.home); | ||
| 79 | +}; | ||
| 80 | + | ||
| 41 | // 로그아웃을 클릭하면 LogOut페이지로 가는 것 대신에, 로그아웃을 처리한 후 | 81 | // 로그아웃을 클릭하면 LogOut페이지로 가는 것 대신에, 로그아웃을 처리한 후 |
| 42 | // home 페이지로 Redirect로 표현할 것이다. | 82 | // home 페이지로 Redirect로 표현할 것이다. |
| 43 | // 즉, 초반에 만들어둔 logout.pug는 삭제해도 좋다. | 83 | // 즉, 초반에 만들어둔 logout.pug는 삭제해도 좋다. |
| 44 | export const logout = (req, res) => { | 84 | export const logout = (req, res) => { |
| 45 | // res.render("logout", { pageTitle: "Logout" }); | 85 | // res.render("logout", { pageTitle: "Logout" }); |
| 86 | + req.logout(); | ||
| 46 | res.redirect(routes.home); | 87 | res.redirect(routes.home); |
| 47 | }; | 88 | }; |
| 48 | 89 | ... | ... |
| 1 | +dotenv.config(); | ||
| 1 | import dotenv from "dotenv"; | 2 | import dotenv from "dotenv"; |
| 2 | import app from "./app"; // app.js에서 export default app했기 때문에 불러올 수 있다. | 3 | import app from "./app"; // app.js에서 export default app했기 때문에 불러올 수 있다. |
| 3 | import "./db"; | 4 | import "./db"; |
| ... | @@ -5,8 +6,6 @@ import "./models/Video"; | ... | @@ -5,8 +6,6 @@ import "./models/Video"; |
| 5 | import "./models/Comment"; | 6 | import "./models/Comment"; |
| 6 | import "./models/User"; | 7 | import "./models/User"; |
| 7 | 8 | ||
| 8 | -dotenv.config(); | ||
| 9 | - | ||
| 10 | const PORT = process.env.PORT || 80; | 9 | const PORT = process.env.PORT || 80; |
| 11 | 10 | ||
| 12 | const handleListening = () => { | 11 | const handleListening = () => { | ... | ... |
| ... | @@ -35,6 +35,7 @@ | ... | @@ -35,6 +35,7 @@ |
| 35 | "multer": "^1.4.2", | 35 | "multer": "^1.4.2", |
| 36 | "node-sass": "^4.14.1", | 36 | "node-sass": "^4.14.1", |
| 37 | "passport": "^0.4.1", | 37 | "passport": "^0.4.1", |
| 38 | + "passport-github": "^1.1.0", | ||
| 38 | "passport-local": "^1.0.0", | 39 | "passport-local": "^1.0.0", |
| 39 | "passport-local-mongoose": "^6.0.1", | 40 | "passport-local-mongoose": "^6.0.1", |
| 40 | "postcss-loader": "^3.0.0", | 41 | "postcss-loader": "^3.0.0", | ... | ... |
| 1 | +import dotenv from "dotenv"; | ||
| 1 | import passport from "passport"; | 2 | import passport from "passport"; |
| 3 | +import GithubStrategy from "passport-github"; | ||
| 2 | import User from "./models/User"; | 4 | import User from "./models/User"; |
| 5 | +import { githubLoginCallback } from "./controllers/userController"; | ||
| 6 | +import routes from "./routes"; | ||
| 3 | 7 | ||
| 8 | +dotenv.config(); | ||
| 4 | // passport에게 strategy(로그인 방식)를 사용하도록 요청한다. | 9 | // passport에게 strategy(로그인 방식)를 사용하도록 요청한다. |
| 5 | // passportLocalMongooser가 제공하는 strategy를 이용한다. -> username과 password를 사용. | 10 | // passportLocalMongooser가 제공하는 strategy를 이용한다. -> username과 password를 사용. |
| 6 | passport.use(User.createStrategy()); | 11 | passport.use(User.createStrategy()); |
| 7 | 12 | ||
| 13 | +passport.use( | ||
| 14 | + new GithubStrategy( | ||
| 15 | + { | ||
| 16 | + clientID: process.env.GH_ID, | ||
| 17 | + clientSecret: process.env.GH_SECRET, | ||
| 18 | + callbackURL: `http://localhost:80${routes.githubCallback}`, | ||
| 19 | + }, | ||
| 20 | + githubLoginCallback | ||
| 21 | + ) | ||
| 22 | +); | ||
| 23 | + | ||
| 8 | passport.serializeUser(User.serializeUser()); | 24 | passport.serializeUser(User.serializeUser()); |
| 9 | passport.deserializeUser(User.deserializeUser()); | 25 | passport.deserializeUser(User.deserializeUser()); | ... | ... |
| 1 | import express from "express"; | 1 | import express from "express"; |
| 2 | +import passport from "passport"; | ||
| 2 | import routes from "../routes"; | 3 | import routes from "../routes"; |
| 3 | import { home, search } from "../controllers/videoController"; | 4 | import { home, search } from "../controllers/videoController"; |
| 4 | import { | 5 | import { |
| 5 | - logout, | ||
| 6 | getJoin, | 6 | getJoin, |
| 7 | - postJoin, | ||
| 8 | getLogin, | 7 | getLogin, |
| 8 | + logout, | ||
| 9 | + postJoin, | ||
| 9 | postLogin, | 10 | postLogin, |
| 11 | + githubLogin, | ||
| 12 | + postGithubLogin, | ||
| 10 | } from "../controllers/userController"; | 13 | } from "../controllers/userController"; |
| 11 | -import { onlyPublic } from "../middlewares"; | 14 | +import { onlyPublic, onlyPrivate } from "../middlewares"; |
| 12 | 15 | ||
| 13 | const globalRouter = express.Router(); | 16 | const globalRouter = express.Router(); |
| 14 | 17 | ||
| ... | @@ -20,5 +23,15 @@ globalRouter.post(routes.login, onlyPublic, postLogin); | ... | @@ -20,5 +23,15 @@ globalRouter.post(routes.login, onlyPublic, postLogin); |
| 20 | 23 | ||
| 21 | globalRouter.get(routes.home, home); | 24 | globalRouter.get(routes.home, home); |
| 22 | globalRouter.get(routes.search, search); | 25 | globalRouter.get(routes.search, search); |
| 23 | -globalRouter.get(routes.logout, logout); | 26 | +globalRouter.get(routes.logout, onlyPrivate, logout); |
| 27 | + | ||
| 28 | +globalRouter.get(routes.gitHub, githubLogin); | ||
| 29 | +// callback으로 받아온 정보를 다뤄야하는 함수도 필요하다. | ||
| 30 | +// callback으로 가면 passport.authenticate 처리 해줘야함 | ||
| 31 | +globalRouter.get( | ||
| 32 | + routes.githubCallback, | ||
| 33 | + passport.authenticate("github", { failureRedirect: "/login" }), | ||
| 34 | + postGithubLogin | ||
| 35 | +); | ||
| 36 | + | ||
| 24 | export default globalRouter; | 37 | export default globalRouter; | ... | ... |
| ... | @@ -18,6 +18,10 @@ const VIDEO_DETAIL = "/:id"; | ... | @@ -18,6 +18,10 @@ const VIDEO_DETAIL = "/:id"; |
| 18 | const EDIT_VIDEO = "/:id/edit"; | 18 | const EDIT_VIDEO = "/:id/edit"; |
| 19 | const DELETE_VIDEO = "/:id/delete"; | 19 | const DELETE_VIDEO = "/:id/delete"; |
| 20 | 20 | ||
| 21 | +// Github | ||
| 22 | +const GITHUB = "/auth/github"; | ||
| 23 | +const GITHUB_CALLBACK = "/auth/github/callback"; | ||
| 24 | + | ||
| 21 | const routes = { | 25 | const routes = { |
| 22 | home: HOME, | 26 | home: HOME, |
| 23 | join: JOIN, | 27 | join: JOIN, |
| ... | @@ -57,6 +61,8 @@ const routes = { | ... | @@ -57,6 +61,8 @@ const routes = { |
| 57 | return DELETE_VIDEO; | 61 | return DELETE_VIDEO; |
| 58 | } | 62 | } |
| 59 | }, | 63 | }, |
| 64 | + gitHub: GITHUB, | ||
| 65 | + githubCallback: GITHUB_CALLBACK, | ||
| 60 | }; | 66 | }; |
| 61 | // template에서 직접 접근이 필요한 경우 함수로 바꿔준다. | 67 | // template에서 직접 접근이 필요한 경우 함수로 바꿔준다. |
| 62 | export default routes; | 68 | export default routes; | ... | ... |
| ... | @@ -2,4 +2,26 @@ express session을 설치한다. npm install express-session | ... | @@ -2,4 +2,26 @@ express session을 설치한다. npm install express-session |
| 2 | 2 | ||
| 3 | postJoin은 이메일과 비밀번호를 전달하고 next()가 호출되어 postLogin으로 간다. | 3 | postJoin은 이메일과 비밀번호를 전달하고 next()가 호출되어 postLogin으로 간다. |
| 4 | 4 | ||
| 5 | -connect mongo를 통해 저장소를 생성한다. | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 5 | +connect mongo를 통해 저장소를 생성한다. | ||
| 6 | + | ||
| 7 | +- 인증에 대한 정리 - | ||
| 8 | +유저네임과 비밀번호를 이용한 방식(local 방식)은 비교적 간단하다. 유저네임과 비밀번호를 post 방식으로 전달하고 | ||
| 9 | +설치해준 플러그인인 Mongoose가 자동으로 체크를 해준다. 만약 비밀번호가 맞으면 passport에게 맞다고 알려주고 | ||
| 10 | +passport는 쿠키를 생성한다. | ||
| 11 | + | ||
| 12 | +소셜로그인의 경우에는 조금 다르다 | ||
| 13 | +먼저 사용자는 깃허브 사이트로 이동하게 되고 거기에서 권한 승인을 한다. | ||
| 14 | +그 이후에 깃헙 사이트는 우리에게 해당 사용자의 정보를 보내주는데 /auth/github/callback이라는 URL로 오게 된다 | ||
| 15 | +그렇게 되면 passport가 함수를 호출하는데 githubLoginCallback이라는 우리가 만들어준 함수이다. | ||
| 16 | +passport가 이함수를 실행하는 것이다. | ||
| 17 | +이 함수는 모든 사용자 프로필 정보를 받고 이 정보로 필요한 것을 할 수 있다. | ||
| 18 | +githubLoginCallback 함수의 한가지 조건은 callback(cb) 함수를 리턴해야하는 것이다. | ||
| 19 | +cb 함수를 실행시켜서 에러가 있는지 유저가 있는지 알려줘야 한다. | ||
| 20 | + | ||
| 21 | +에러가 존재하면 passport는 에러가 있구나 유저는 없구나하고 끝내고 | ||
| 22 | +유저가 존재하면 passport는 이 유저를 가져와 쿠키를 만들고 저장한다. | ||
| 23 | +이렇게 저장된 쿠키를 브라우저로 보내게 된다. | ||
| 24 | + | ||
| 25 | +globalRouter에서 깃허브로 갈때 githubLogin이 실행되는데 깃허브로 보내주는 역할을 한다. | ||
| 26 | +그리고 githubCallback(URL)로 돌아왔을 때 passport는 사용자가 알려준 함수인 githubLoginCallback을 실행시킨다. | ||
| 27 | +만약 user를 찾으면 passport는 통과시키며 postGithubLogin을 실행하고 홈으로 리다이렉트한다. | ... | ... |
| 1 | .social-login | 1 | .social-login |
| 2 | button.social-login--github | 2 | button.social-login--github |
| 3 | - span | 3 | + a(href=routes.gitHub) |
| 4 | - i.fab.fa-github | 4 | + span |
| 5 | - | Continue with Github | 5 | + i.fab.fa-github |
| 6 | + | Continue with Github | ||
| 6 | button.social-login--facebook | 7 | button.social-login--facebook |
| 7 | span | 8 | span |
| 8 | i.fab.fa-facebook | 9 | i.fab.fa-facebook | ... | ... |
-
Please register or login to post a comment