This repository has been archived by the owner on May 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathindex.js
156 lines (135 loc) · 4.47 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
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* eslint-disable no-console */
const Provider = require('oidc-provider');
const path = require('path');
const { set } = require('lodash');
const bodyParser = require('koa-body');
const querystring = require('querystring');
const Router = require('koa-router');
const render = require('koa-ejs');
const express = require('express');
const cors = require('cors');
const app = express();
const Account = require('./account');
const { config, clients, certificates} = require('./settings');
const port = process.env.PORT || 8080;
const issuer = process.env.ISSUER || 'https://localhost:8080';
//AAD specific header, can only be set by azure when running as AppService
const PRINCIPAL_NAME_HEADER = 'x-ms-client-principal-name';
const DOMAIN_HINT = process.env.DOMAIN_HINT || 'nav.no';
const DEBUG_REQUEST = process.env.DEBUG_REQUEST || false;
config.findById = Account.findById;
const provider = new Provider(issuer, config);
provider.defaultHttpOptions = { timeout: 15000 };
function enforceAuthenticationIfEnabled(ctx){
if(process.env['WEBSITE_AUTH_ENABLED'] === 'True'){
console.log('Authentication is enabled for site, check required headers');
if (!ctx.get(PRINCIPAL_NAME_HEADER)){
console.log('no principal id, found redirecting to /.auth/login/aad');
ctx.redirect('/.auth/login/aad?domain_hint='+ DOMAIN_HINT +'&post_login_redirect_url=' + ctx.url);
}
} else {
console.log('Authentication is NOT enabled for site. Value of WEBSITE_AUTH_ENABLED=' + process.env['WEBSITE_AUTH_ENABLED']);
}
}
provider.initialize({
clients,
keystore: { keys: certificates },
}).then(() => {
render(provider.app, {
cache: false,
layout: '_layout',
root: path.join(__dirname, 'views'),
});
if (process.env.NODE_ENV === 'hosted') {
provider.proxy = true;
set(config, 'cookies.short.secure', true);
set(config, 'cookies.long.secure', true);
provider.use(async (ctx, next) => {
if (ctx.secure) {
await next();
} else if (ctx.method === 'GET' || ctx.method === 'HEAD') {
ctx.redirect(ctx.href.replace(/^http:\/\//i, 'https://'));
} else {
ctx.body = {
error: 'invalid_request',
error_description: 'only use https',
};
ctx.status = 400;
}
});
}
const router = new Router();
router.get('/interaction/:grant', async (ctx, next) => {
const details = await provider.interactionDetails(ctx.req);
const client = await provider.Client.find(details.params.client_id);
enforceAuthenticationIfEnabled(ctx);
if (details.interaction.error === 'login_required') {
await ctx.render('login', {
client,
details,
title: 'Sign-in as:',
principalName: ctx.request.header[PRINCIPAL_NAME_HEADER] || 'anonymous',
debug: querystring.stringify(details.params, ',<br/>', ' = ', {
encodeURIComponent: value => value,
}),
interaction: querystring.stringify(details.interaction, ',<br/>', ' = ', {
encodeURIComponent: value => value,
}),
});
} else {
await ctx.render('interaction', {
client,
details,
title: 'Authorize',
debug: querystring.stringify(details.params, ',<br/>', ' = ', {
encodeURIComponent: value => value,
}),
interaction: querystring.stringify(details.interaction, ',<br/>', ' = ', {
encodeURIComponent: value => value,
}),
});
}
await next();
});
const body = bodyParser();
router.post('/interaction/:grant/confirm', body, async (ctx, next) => {
enforceAuthenticationIfEnabled(ctx);
const result = { consent: {} };
await provider.interactionFinished(ctx.req, ctx.res, result);
await next();
});
router.post('/interaction/:grant/login', body, async (ctx, next) => {
enforceAuthenticationIfEnabled(ctx);
const principalName = ctx.request.header[PRINCIPAL_NAME_HEADER] || 'anonymous';
const account = new Account(ctx.request.body.login, principalName);
const details = await provider.interactionDetails(ctx.req);
const result = {
login: {
account: account.accountId,
acr: details.params.acr_values || 'Level3',
amr: 'BankID',
remember: !!ctx.request.body.remember,
ts: Math.floor(Date.now() / 1000),
},
consent: {},
};
await provider.interactionFinished(ctx.req, ctx.res, result);
await next();
});
router.get('/*', body, async (ctx, next) => {
if(DEBUG_REQUEST){
console.log('GET request:' + JSON.stringify(ctx.request));
}
await next();
});
provider.use(router.routes());
})
.then(() => {
app.use(cors());
app.use(provider.callback);
app.listen(port);
})
.catch((err) => {
console.error(err);
process.exitCode = 1;
});