From acc5dcc85125f933125d527aedbb01f7fd49f5c5 Mon Sep 17 00:00:00 2001
From: tpgus2603 <kakaneymar2424@gmail.com>
Date: Thu, 14 Nov 2024 12:22:07 +0900
Subject: [PATCH] =?UTF-8?q?feat=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=B2=98?=
 =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20?=
 =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#2)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .env                       | 10 ++++
 app.js                     | 42 +++++++++++++++++
 middleware/auth.js         | 15 ++++++
 package-lock.json          | 95 ++++++++++++++++++++++++++++++++++++++
 package.json               |  3 ++
 passport/googleStrategy.js | 29 ++++++++++++
 passport/index.js          | 25 ++++++++++
 routes/auth.js             | 35 ++++++++++++++
 8 files changed, 254 insertions(+)
 create mode 100644 .env
 create mode 100644 middleware/auth.js
 create mode 100644 passport/googleStrategy.js
 create mode 100644 passport/index.js

diff --git a/.env b/.env
new file mode 100644
index 0000000..5974096
--- /dev/null
+++ b/.env
@@ -0,0 +1,10 @@
+DB_HOST=localhost
+DB_USER=root
+DB_PASSWORD=0000
+DB_NAME=meeting
+MONGO_URI=mongodb://localhost:27017/your_mongo_db
+PORT=8080
+
+GOOGLE_CLIENT_ID=552188448115-ice40pervgq9s0me3sme59fjpsia7sm2.apps.googleusercontent.com
+GOOGLE_CLIENT_SECRET=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
+CALLBACK_URL=http://localhost:8080/auth/google/callback
\ No newline at end of file
diff --git a/app.js b/app.js
index 30e4db3..310461c 100644
--- a/app.js
+++ b/app.js
@@ -1,5 +1,47 @@
+<<<<<<< Updated upstream
+=======
+// app.js
+
+require('dotenv').config();
+
+>>>>>>> Stashed changes
 const express = require('express');
+const session = require('express-session');
+const passport = require('./passport'); // 변경된 경로
+const flash = require('connect-flash');
+
 const app = express();
+<<<<<<< Updated upstream
+=======
+
+// 미들웨어 설정
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+
+// 세션 설정
+app.use(
+  session({
+    secret: 'your_session_secret', 
+    resave: false,
+    saveUninitialized: false,
+  })
+);
+
+// Passport 초기화 및 세션 연결
+app.use(passport.initialize());
+app.use(passport.session());
+
+// 플래시 메시지 (선택 사항)
+app.use(flash());
+
+// 라우트 설정
+const authRoutes = require('./routes/auth');
+app.use('/auth', authRoutes);
+
+// ... 다른 라우트 및 설정
+
+// 서버 시작
+>>>>>>> Stashed changes
 const PORT = process.env.PORT || 3000;
 
 app.get('/', (req, res) => {
diff --git a/middleware/auth.js b/middleware/auth.js
new file mode 100644
index 0000000..8ae9be0
--- /dev/null
+++ b/middleware/auth.js
@@ -0,0 +1,15 @@
+// middlewares/auth.js
+
+exports.isLoggedIn = (req, res, next) => {
+  if (req.isAuthenticated()) {
+    return next();
+  }
+  res.redirect('/auth/login');
+};
+
+exports.isNotLoggedIn = (req, res, next) => {
+  if (!req.isAuthenticated()) {
+    return next();
+  }
+  res.redirect('/');
+};
diff --git a/package-lock.json b/package-lock.json
index 1a8403b..5b6f0cb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
       "version": "1.0.0",
       "license": "ISC",
       "dependencies": {
+        "connect-flash": "^0.1.1",
         "cookie-parser": "^1.4.7",
         "dotenv": "^16.4.5",
         "express": "^4.21.1",
@@ -17,6 +18,8 @@
         "morgan": "^1.10.0",
         "multer": "^1.4.5-lts.1",
         "mysql2": "^3.11.4",
+        "passport": "^0.7.0",
+        "passport-google-oauth20": "^2.0.0",
         "sequelize": "^6.37.5",
         "sequelize-cli": "^6.6.2"
       },
@@ -207,6 +210,15 @@
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
       "license": "MIT"
     },
+    "node_modules/base64url": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz",
+      "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
     "node_modules/basic-auth": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
@@ -528,6 +540,14 @@
         "proto-list": "~1.2.1"
       }
     },
+    "node_modules/connect-flash": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
+      "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA==",
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
     "node_modules/content-disposition": {
       "version": "0.5.4",
       "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -1971,6 +1991,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/oauth": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz",
+      "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==",
+      "license": "MIT"
+    },
     "node_modules/object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -2028,6 +2054,64 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/passport": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz",
+      "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==",
+      "license": "MIT",
+      "dependencies": {
+        "passport-strategy": "1.x.x",
+        "pause": "0.0.1",
+        "utils-merge": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/jaredhanson"
+      }
+    },
+    "node_modules/passport-google-oauth20": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz",
+      "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==",
+      "license": "MIT",
+      "dependencies": {
+        "passport-oauth2": "1.x.x"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/passport-oauth2": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz",
+      "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==",
+      "license": "MIT",
+      "dependencies": {
+        "base64url": "3.x.x",
+        "oauth": "0.10.x",
+        "passport-strategy": "1.x.x",
+        "uid2": "0.0.x",
+        "utils-merge": "1.x.x"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/jaredhanson"
+      }
+    },
+    "node_modules/passport-strategy": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
+      "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==",
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
     "node_modules/path-key": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -2071,6 +2155,11 @@
       "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
       "license": "MIT"
     },
+    "node_modules/pause": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
+      "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
+    },
     "node_modules/pg-connection-string": {
       "version": "2.7.0",
       "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz",
@@ -2822,6 +2911,12 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/uid2": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz",
+      "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==",
+      "license": "MIT"
+    },
     "node_modules/umzug": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz",
diff --git a/package.json b/package.json
index e756213..9f213ea 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
   "license": "ISC",
   "description": "",
   "dependencies": {
+    "connect-flash": "^0.1.1",
     "cookie-parser": "^1.4.7",
     "dotenv": "^16.4.5",
     "express": "^4.21.1",
@@ -21,6 +22,8 @@
     "morgan": "^1.10.0",
     "multer": "^1.4.5-lts.1",
     "mysql2": "^3.11.4",
+    "passport": "^0.7.0",
+    "passport-google-oauth20": "^2.0.0",
     "sequelize": "^6.37.5",
     "sequelize-cli": "^6.6.2"
   },
diff --git a/passport/googleStrategy.js b/passport/googleStrategy.js
new file mode 100644
index 0000000..c5964ef
--- /dev/null
+++ b/passport/googleStrategy.js
@@ -0,0 +1,29 @@
+// passport/googleStrategy.js
+
+const { Strategy: GoogleStrategy } = require('passport-google-oauth20');
+const User = require('../models/User');
+
+module.exports = new GoogleStrategy(
+  {
+    clientID: process.env.GOOGLE_CLIENT_ID, // .env 파일에 설정
+    clientSecret: process.env.GOOGLE_CLIENT_SECRET,
+    callbackURL: process.env.CALLBACK_URL,
+  },
+  async (accessToken, refreshToken, profile, done) => {
+    try {
+      // 프로필에서 사용자 정보 추출
+      const email = profile.emails[0].value;
+      const name = profile.displayName;
+
+      // 데이터베이스에서 사용자 찾거나 생성
+      let user = await User.findOne({ where: { email } });
+      if (!user) {
+        user = await User.create({ email, name });
+      }
+
+      return done(null, user);
+    } catch (err) {
+      return done(err);
+    }
+  }
+);
diff --git a/passport/index.js b/passport/index.js
new file mode 100644
index 0000000..6f12584
--- /dev/null
+++ b/passport/index.js
@@ -0,0 +1,25 @@
+// passport/index.js
+
+const passport = require('passport');
+const User = require('../models/User');
+
+// 직렬화
+passport.serializeUser((user, done) => {
+  done(null, user.id);
+});
+
+// 역직렬화
+passport.deserializeUser(async (id, done) => {
+  try {
+    const user = await User.findByPk(id);
+    done(null, user);
+  } catch (err) {
+    done(err);
+  }
+});
+
+// 전략 가져오기
+const googleStrategy = require('./googleStrategy');
+passport.use(googleStrategy);
+
+module.exports = passport;
diff --git a/routes/auth.js b/routes/auth.js
index e69de29..7eda249 100644
--- a/routes/auth.js
+++ b/routes/auth.js
@@ -0,0 +1,35 @@
+// routes/auth.js
+
+const express = require('express');
+const passport = require('passport');
+
+const router = express.Router();
+
+// GET /auth/login
+router.get('/login', (req, res) => {
+  res.send('<a href="/auth/google">Log in with Google</a>');
+});
+
+// GET /auth/logout
+router.get('/logout', (req, res) => {
+  req.logout(() => {
+    res.redirect('/');
+  });
+});
+
+// GET /auth/google
+router.get(
+  '/google',
+  passport.authenticate('google', { scope: ['profile', 'email'] })
+);
+
+// GET /auth/google/callback
+router.get(
+  '/google/callback',
+  passport.authenticate('google', { failureRedirect: '/auth/login' }),
+  (req, res) => {
+    res.redirect('/');
+  }
+);
+
+module.exports = router;
-- 
GitLab