Build a Node.js Express server that authenticates users through Google OAuth 2.0 and allows them to access protected resources once authenticated. Store user information in a MongoDB database.
PLAINFORMAT
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const mongoose = require('mongoose');
const cookieSession = require('cookie-session');
const auth = require('./auth');
const User = require('./models/user');

// Connect to MongoDB
mongoose.connect(process.env.MONGO_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(
  cookieSession({
    maxAge: 24 * 60 * 60 * 1000,
    keys: [process.env.COOKIE_KEY],
  })
);

app.set('view engine', 'ejs');

app.get('/', (req, res) => {
  res.render('index');
});

app.post('/login', async (req, res) => {
  try {
    const payload = await auth.verify(req.body.idtoken);
    const existingUser = await User.findOne({ googleId: payload.sub });

    if (existingUser) {
      req.session.userId = existingUser._id;
      res.redirect('/dashboard');
    } else {
      const newUser = await new User({ googleId: payload.sub }).save();
      req.session.userId = newUser._id;
      res.redirect('/dashboard');
    }
  } catch (error) {
    console.error(error);
    res.status(401).send('Unauthorized');
  }
});

app.get('/logout', (req, res) => {
  req.session = null;
  res.redirect('/');
});

function requireLogin(req, res, next) {
  if (!req.session.userId) {
    return res.status(401).send('Unauthorized');
  }
  next();
}

app.get('/dashboard', requireLogin, (req, res) => {
  res.send('Welcome to the dashboard!');
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});