-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
93 lines (83 loc) · 2.65 KB
/
index.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
const URL = require('url');
const express = require('express');
const axios = require('axios');
const jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');
const uuid = require('uuid/v4');
const defaultConfig = require('./config');
/**
* Middleware that can be used in express to implement a set of routes
* to enable OIDC authentication with ubsub
* @param {object} options to override config.oidc
* @return {Router} Express router
*/
module.exports = function buildOidcProxy(opts = defaultConfig.oidc) {
const router = express.Router();
function validateConf(item) {
if (!opts[item]) {
console.error(`WARNING: Missing required config '${item}'! OIDC Middleware may not work`);
}
}
validateConf('client_id');
validateConf('client_secret');
validateConf('auth_url');
validateConf('token_url');
router.use(cookieParser());
router.get('/', (req, res) => {
const state = uuid();
const uri = URL.parse(opts.auth_url, true);
if (!uri.query) {
uri.query = {};
}
uri.query.client_id = opts.client_id;
uri.query.response_type = 'code';
uri.query.scope = opts.scope;
uri.query.redirect_uri = `${opts.redirect_base}/validate`;
uri.query.state = state;
if (opts.layout) {
uri.query.layout = opts.layout;
}
res.cookie('ubsubOidcState', state, { httpOnly: true });
res.redirect(URL.format(uri));
});
router.get('/validate', (req, res, next) => {
const { state, code } = req.query;
const cookiedState = req.cookies.ubsubOidcState;
res.clearCookie('ubsubOidcState');
if (state !== cookiedState) {
return next(new Error('Failed to authenticate OIDC state cookie'));
}
return axios.post(opts.token_url, {
client_id: opts.client_id,
client_secret: opts.client_secret,
grant_type: 'authorization_code',
code,
}).then((resp) => {
const token = resp.data;
return new Promise((resolve, reject) => {
jwt.verify(token.id_token, opts.client_secret, (err, decoded) => {
if (err) {
return reject(err);
}
if (opts.parseToken) {
token.jwt = decoded;
}
return resolve(token);
});
});
}).then((token) => {
if (opts.store === 'cookie') {
res.cookie(opts.storeName, JSON.stringify(token), opts.storeOpts);
} else if (opts.store !== 'none') {
console.log(`WARNING: Invalid store set ${opts.store}`);
}
res.redirect(opts.success_url);
}).catch((err) => {
if (opts.error_url) {
return res.redirect(opts.error_url);
}
return next(err);
});
});
return router;
};