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