diff --git a/app.js b/app.js index f8de6b4..87b21d7 100644 --- a/app.js +++ b/app.js @@ -1,13 +1,20 @@ const path = require('path') const express = require('express') +const mongoose = require('mongoose') const dotenv = require('dotenv') const morgan = require('morgan') const exphbs = require('express-handlebars') +const passport = require('passport') +const session = require('express-session') +const MongoStore = require('connect-mongo')(session) const connectDB = require('./config/db') // Load config dotenv.config({ path: './config/config.env' }) +// Passport config +require('./config/passport')(passport) + connectDB() const app = express() @@ -27,11 +34,26 @@ app.engine( ) app.set('view engine', '.hbs') +// Sessions +app.use( + session({ + secret: 'keyboard cat', + resave: false, + saveUninitialized: false, + store: new MongoStore({ mongooseConnection: mongoose.connection }), + }) +) + +// Passport middleware +app.use(passport.initialize()) +app.use(passport.session()) + // Static folder app.use(express.static(path.join(__dirname, 'public'))) // Routes app.use('/', require('./routes/index')) +app.use('/auth', require('./routes/auth')) const PORT = process.env.PORT || 3000 diff --git a/config/passport.js b/config/passport.js new file mode 100644 index 0000000..3b18c85 --- /dev/null +++ b/config/passport.js @@ -0,0 +1,45 @@ +const GoogleStrategy = require('passport-google-oauth20').Strategy +const mongoose = require('mongoose') +const User = require('../models/User') + +module.exports = function (passport) { + passport.use( + new GoogleStrategy( + { + clientID: process.env.GOOGLE_CLIENT_ID, + clientSecret: process.env.GOOGLE_CLIENT_SECRET, + callbackURL: '/auth/google/callback', + }, + async (accessToken, refreshToken, profile, done) => { + const newUser = { + googleId: profile.id, + displayName: profile.displayName, + firstName: profile.name.givenName, + lastName: profile.name.familyName, + image: profile.photos[0].value, + } + + try { + let user = await User.findOne({ googleId: profile.id }) + + if (user) { + done(null, user) + } else { + user = await User.create(newUser) + done(null, user) + } + } catch (err) { + console.error(err) + } + } + ) + ) + + passport.serializeUser((user, done) => { + done(null, user.id) + }) + + passport.deserializeUser((id, done) => { + User.findById(id, (err, user) => done(err, user)) + }) +} diff --git a/models/User.js b/models/User.js new file mode 100644 index 0000000..643029a --- /dev/null +++ b/models/User.js @@ -0,0 +1,29 @@ +const mongoose = require('mongoose') + +const UserSchema = new mongoose.Schema({ + googleId: { + type: String, + required: true, + }, + displayName: { + type: String, + required: true, + }, + firstName: { + type: String, + required: true, + }, + lastName: { + type: String, + required: true, + }, + image: { + type: String, + }, + createdAt: { + type: Date, + default: Date.now, + }, +}) + +module.exports = mongoose.model('User', UserSchema) diff --git a/routes/auth.js b/routes/auth.js new file mode 100644 index 0000000..714292f --- /dev/null +++ b/routes/auth.js @@ -0,0 +1,26 @@ +const express = require('express') +const passport = require('passport') +const router = express.Router() + +// @desc Auth with Google +// @route GET /auth/google +router.get('/google', passport.authenticate('google', { scope: ['profile'] })) + +// @desc Google auth callback +// @route GET /auth/google/callback +router.get( + '/google/callback', + passport.authenticate('google', { failureRedirect: '/' }), + (req, res) => { + res.redirect('/dashboard') + } +) + +// @desc Logout user +// @route /auth/logout +router.get('/logout', (req, res) => { + req.logout() + res.redirect('/') +}) + +module.exports = router