generated from hack4impact-uiuc/mern-template
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Enable connection to Mongo * Install passport and express-session * Change most member attributes to not required * Add auth routes * Add passport setup with cookie sessions * Add options for express-session * Add options for express-session * Move passport-setup to root * Add middleware for auth * Change auth routes to use result instead of data * Add protected route as an example * Remove home test and replace with dummy test * Remove dummy test * Remove console.log * Remove extra || null * Add back home.test.js and new env vars to api.yaml * Add example dev.env * Add redirectURI endpoint to allow for changing Vercel subdomains * Add redirect URLs as parameters for /login * Format auth.js * Remove FRONTEND_URI from example env file * Enable failure flash * Add back .env files * Add vercel env vars * Remove OAUTH_CALLBACK_URI from production env
- Loading branch information
Showing
17 changed files
with
354 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
MONGO_URL= | ||
GOOGLE_CLIENT_ID= | ||
GOOGLE_CLIENT_SECRET= | ||
SESSION_SECRET=keyboard cat | ||
OAUTH_CALLBACK_URI=http://localhost:9000/api/auth/redirectURI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
MONGO_URL=mongodb://localhost | ||
GOOGLE_CLIENT_ID= | ||
GOOGLE_CLIENT_SECRET= | ||
SESSION_SECRET= | ||
OAUTH_CALLBACK_URI=http://localhost:9000/api/auth/redirectURI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +0,0 @@ | ||
MONGO_URL=production-mongo | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
MONGO_URL=test-mongo | ||
MONGO_URL= | ||
GOOGLE_CLIENT_ID= | ||
GOOGLE_CLIENT_SECRET= | ||
SESSION_SECRET= | ||
OAUTH_CALLBACK_URI=http://localhost:9000/api/auth/redirectURI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
const express = require('express'); | ||
const router = express.Router(); | ||
const passport = require('passport'); | ||
|
||
// Defines the callback endpoint which will be passed to LAH's redirect URI | ||
// via Google OAuth's state parameter | ||
const CALLBACK_ENDPOINT = '/api/auth/callback'; | ||
|
||
router.get('/user', (req, res) => { | ||
res.json({ | ||
result: req.user || null, | ||
success: true, | ||
}); | ||
}); | ||
|
||
router.get('/login', (req, res, next) => { | ||
// Get URLs to redirect to on success and failure | ||
const { successRedirect = '/', failureRedirect = '/login' } = req.query; | ||
// Construct the "callback" url by concatenating the current base URL (host) with the callback URL | ||
// We do all this to use one single callback URL so it works with Vercel deploying on multiple | ||
// domains. See LAH's api/auth/login.js for more details on how this works | ||
const callbackUrl = `${req.protocol}://${req.get( | ||
'host', | ||
)}${CALLBACK_ENDPOINT}`; | ||
// State object that will be passed to OAuth and back to our callback | ||
const state = { | ||
callbackUrl, | ||
successRedirect, | ||
failureRedirect, | ||
}; | ||
|
||
const auth = passport.authenticate('google', { | ||
scope: ['profile', 'email'], | ||
state: Buffer.from(JSON.stringify(state)).toString('base64'), | ||
}); | ||
auth(req, res, next); | ||
}); | ||
|
||
router.get('/redirectURI', (req, res) => { | ||
try { | ||
// If we are here, this endpoint is likely being run on the MAIN deployment | ||
const { state } = req.query; | ||
// Grab the branch deployment (lah-branch-deploy.hack4impact.now.sh) for example | ||
const { callbackUrl } = JSON.parse(Buffer.from(state, 'base64').toString()); | ||
if (typeof callbackUrl === 'string') { | ||
// Reconstruct the URL and redirect | ||
const callbackURL = `${callbackUrl}?${req._parsedUrl.query}`; | ||
return res.redirect(callbackURL); | ||
} | ||
// There was no base | ||
return res.redirect(CALLBACK_ENDPOINT); | ||
} catch (e) { | ||
return res.status(400).json({ | ||
message: 'Something went wrong with the URL redirection', | ||
success: false, | ||
}); | ||
} | ||
}); | ||
|
||
router.get( | ||
'/callback', | ||
(req, res, next) => { | ||
const { state } = req.query; | ||
const { successRedirect, failureRedirect } = JSON.parse( | ||
Buffer.from(state, 'base64').toString(), | ||
); | ||
|
||
const auth = passport.authenticate('google', { | ||
successRedirect, | ||
failureRedirect, | ||
failureFlash: true, | ||
}); | ||
auth(req, res, next); | ||
}, | ||
(req, res) => { | ||
// Successful authentication, redirect home. | ||
res.redirect(LOGIN_SUCCESS_REDIRECT); | ||
}, | ||
); | ||
|
||
router.post('/logout', (req, res) => { | ||
req.logout(); | ||
res.json({ | ||
message: 'Logged out', | ||
success: true, | ||
}); | ||
}); | ||
|
||
module.exports = router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
const home = require('./home'); | ||
const auth = require('./auth'); | ||
|
||
module.exports = { | ||
home, | ||
auth, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
const { levelEnum } = require('../models/member'); | ||
|
||
const requireLevel = (levels) => (req, res, next) => { | ||
console.log(req.user); | ||
if (!req.user || !levels.includes(req.user.level)) { | ||
return res.status(401).json({ | ||
success: false, | ||
message: 'Unauthorized', | ||
}); | ||
} else { | ||
next(); | ||
} | ||
}; | ||
|
||
const requireRegistered = requireLevel(Object.values(levelEnum)); | ||
|
||
const requireMember = requireLevel([ | ||
levelEnum.ADMIN, | ||
levelEnum.DIRECTOR, | ||
levelEnum.LEAD, | ||
levelEnum.MEMBER, | ||
]); | ||
|
||
const requireLead = requireLevel([ | ||
levelEnum.ADMIN, | ||
levelEnum.DIRECTOR, | ||
levelEnum.LEAD, | ||
]); | ||
|
||
const requireDirector = requireLevel([levelEnum.ADMIN, levelEnum.DIRECTOR]); | ||
|
||
const requireAdmin = requireLevel([levelEnum.ADMIN]); | ||
|
||
module.exports = { | ||
requireLevel, | ||
requireRegistered, | ||
requireMember, | ||
requireLead, | ||
requireDirector, | ||
requireAdmin, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
const errorHandler = require('./errorHandler'); | ||
const errorWrap = require('./errorWrap'); | ||
const auth = require('./auth'); | ||
|
||
module.exports = { | ||
errorHandler, | ||
errorWrap, | ||
auth, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
const GoogleStrategy = require('passport-google-oauth20').Strategy; | ||
const passport = require('passport'); | ||
const Member = require('./models/member'); | ||
|
||
// Defines the default level a user gets assigned with upon first sign-in | ||
const DEFAULT_LEVEL = process.env.DEFAULT_LEVEL || Member.levelEnum.TBD; | ||
|
||
passport.serializeUser((user, done) => { | ||
done(null, user._id); | ||
}); | ||
|
||
passport.deserializeUser((id, done) => { | ||
// Find in DB and return user | ||
Member.findById(id, (err, user) => { | ||
if (err) { | ||
console.error('err'); | ||
done(err); | ||
} | ||
done(null, user); | ||
}); | ||
}); | ||
|
||
passport.use( | ||
new GoogleStrategy( | ||
{ | ||
clientID: process.env.GOOGLE_CLIENT_ID, | ||
clientSecret: process.env.GOOGLE_CLIENT_SECRET, | ||
callbackURL: process.env.OAUTH_CALLBACK_URI, | ||
}, | ||
async (accessToken, refreshToken, profile, cb) => { | ||
// find the user in the database based on their oauth id | ||
const user = await Member.findOne({ oauthID: profile.id }); | ||
|
||
if (user) { | ||
// user exists | ||
return cb(null, user); | ||
} else { | ||
const newUser = await new Member({ | ||
firstName: profile.name.givenName, | ||
lastName: profile.name.familyName, | ||
oauthID: profile.id, | ||
email: profile.emails[0].value, | ||
level: DEFAULT_LEVEL, | ||
}).save(); | ||
|
||
cb(null, newUser); | ||
} | ||
}, | ||
), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
const express = require('express'); | ||
|
||
const router = express.Router(); | ||
const { home } = require('../api'); | ||
const { home, auth } = require('../api'); | ||
|
||
router.use('/api/home', home); | ||
router.use('/api/auth', auth); | ||
|
||
module.exports = router; |
Oops, something went wrong.