-
Notifications
You must be signed in to change notification settings - Fork 119
/
Copy pathsaml.js
80 lines (71 loc) · 2.99 KB
/
saml.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
'use strict'
// working SAML ADFS example
// no refresh token, issue own OAuth2 like JWT server
const express = require('express')
const passport = require('passport')
const { createToken, setTokensToHeader } = require('@es-labs/node/auth')
const { AUTH_ERROR_URL, SAML_OPTIONS, SAML_JWT_MAP, SAML_DECRYPTION_CERT } = global.CONFIG
const selfsigned = require('selfsigned');
const samlPems = selfsigned.generate(null, { days: 30, algorithm: 'sha256' }) // TO Make this configurable
let samlStrategy
if (SAML_OPTIONS) {
const SamlStrategy = require('passport-saml').Strategy
samlStrategy = new SamlStrategy(
SAML_OPTIONS,
(profile, done) => {
// console.log('profile', profile)
return done(null, { // map whatever claims/profile info you want here
// upn: profile['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'],
// // e.g. if you added a Group claim
// group: profile['http://schemas.xmlsoap.org/claims/Group']
...profile
})
}
)
passport.use('saml', samlStrategy)
}
module.exports = express.Router()
.get('/test', (req,res) => res.send('ok'))
.get('/metadata', (req, res) => {
res.type('application/xml')
// res.status(200).send(samlStrategy.generateServiceProviderMetadata()) // if there is private key involved, then need to pass in cert
res.status(200).send(samlStrategy.generateServiceProviderMetadata(SAML_DECRYPTION_CERT, SAML_OPTIONS.privateCert)) // cert to match decryptionKey, cert to match privateKey
})
.get('/login',
(req, res, next) => {
// return res.redirect('/' + token...) // for faking, bypass real callback
// console.debug(req.header('referer'))
next()
},
passport.authenticate('saml') // , { failureRedirect: '/', failureFlash: true }),
)
// .get('/fail', (req, res) => res.status(401).send('Login Fail')
.post('/callback',
passport.authenticate('saml', { failureRedirect: '/', failureFlash: true }),
async (req, res) => {
try {
const TO = req.body.RelayState
if (!TO) {
return res.status(200).json({
authenticated: req.isAuthenticated(),
user: req.user
})
}
if (req.isAuthenticated()) {
const user = {
id: req.user[SAML_JWT_MAP.id], // id: req.user.nameID, // string
groups: req.user[SAML_JWT_MAP.groups], // groups: req.user.Role, // comma seperated string or array or object...
}
const tokens = await createToken(user)
setTokensToHeader(res, tokens)
return res.redirect(TO + '#' + tokens.access_token + '-' + tokens.refresh_token + '-' + JSON.stringify(tokens.user_meta)) // use url fragment...
} else {
return AUTH_ERROR_URL ? res.redirect(AUTH_ERROR_URL) : res.status(401).json({ error: 'NOT Authenticated' })
}
} catch (e) {
return AUTH_ERROR_URL ? res.redirect(AUTH_ERROR_URL) : res.status(500).json({ error: e.toString() })
}
}
)
// '/logout'
// res.redirect( LOGOUT_URL )