-
Notifications
You must be signed in to change notification settings - Fork 0
/
userAuth.js
130 lines (110 loc) · 4.02 KB
/
userAuth.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
'use strict'
const passport = require('passport')
const session = require('express-session')
const crypto = require('crypto')
const GoogleStrategy = require('passport-google-oauth20')
const SlackStrategy = require('passport-slack-oauth2').Strategy
const log = require('../server/logger')
const {stringTemplate: template} = require('../server/utils')
const router = require('express-promise-router')()
const domains = new Set(process.env.APPROVED_DOMAINS.split(/,\s?/g))
const authStrategies = ['google', 'Slack']
let authStrategy = process.env.OAUTH_STRATEGY
const callbackURL = process.env.REDIRECT_URL || '/auth/redirect'
if (!authStrategies.includes(authStrategy)) {
log.warn(`Invalid oauth strategy ${authStrategy} specific, defaulting to google auth`)
authStrategy = 'google'
}
const isSlackOauth = authStrategy === 'Slack'
if (isSlackOauth) {
passport.use(new SlackStrategy({
clientID: process.env.SLACK_CLIENT_ID,
clientSecret: process.env.SLACK_CLIENT_SECRET,
skipUserProfile: false,
callbackURL,
scope: ['identity.basic', 'identity.email', 'identity.avatar', 'identity.team', 'identity.email']
},
(accessToken, refreshToken, profile, done) => {
// optionally persist user data into a database
done(null, profile)
}
))
} else {
// default to google auth
passport.use(new GoogleStrategy.Strategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL,
userProfileURL: 'https://www.googleapis.com/oauth2/v3/userinfo',
passReqToCallback: true
}, (request, accessToken, refreshToken, profile, done) => done(null, profile)))
}
const md5 = (data) => crypto.createHash('md5').update(data).digest('hex')
router.use(session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true
}))
router.use(passport.initialize())
router.use(passport.session())
// seralize/deseralization methods for extracting user information from the
// session cookie and adding it to the req.passport object
passport.serializeUser((user, done) => done(null, user))
passport.deserializeUser((obj, done) => done(null, obj))
const googleLoginOptions = {
scope: [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'
],
hostedDomain: ["reaktor.fi"]
}
router.get('/login', passport.authenticate(authStrategy, isSlackOauth ? {} : googleLoginOptions))
router.get('/logout', (req, res) => {
req.logout()
res.redirect('/')
})
router.get('/auth/redirect', passport.authenticate(authStrategy, {failureRedirect: '/login'}), (req, res) => {
res.redirect(req.session.authRedirect || '/')
})
router.use((req, res, next) => {
const isDev = process.env.NODE_ENV === 'development'
const passportUser = (req.session.passport || {}).user || {}
if (isDev || (req.isAuthenticated() && isAuthorized(passportUser))) {
setUserInfo(req)
return next()
}
if (req.isAuthenticated() && !isAuthorized(passportUser)) {
return next(Error('Unauthorized'))
}
log.info('User not authenticated')
req.session.authRedirect = req.path
res.redirect('/login')
})
function isAuthorized(user) {
const [{value: userEmail = ''} = {}] = user.emails || []
const [userDomain] = userEmail.split('@').slice(-1)
const checkRegexEmail = () => {
const domainsArray = Array.from(domains)
for (const domain of domainsArray) {
if (userDomain.match(domain)) return true
}
}
return domains.has(userDomain) || domains.has(userEmail) || checkRegexEmail()
}
function setUserInfo(req) {
if (process.env.NODE_ENV === 'development') {
req.userInfo = {
email: process.env.TEST_EMAIL || template('footer.defaultEmail'),
userId: '10',
analyticsUserId: md5('10library')
}
return
}
const email = isSlackOauth ? req.session.passport.user.email : req.session.passport.user.emails[0].value
req.userInfo = req.userInfo ? req.userInfo : {
userId: req.session.passport.user.id,
analyticsUserId: md5(req.session.passport.user.id + 'library'),
email
}
}
module.exports = router