forked from VilledeMontreal/authentication-nodejs-lib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
131 lines (121 loc) · 3.51 KB
/
index.ts
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
import express from 'express';
import {
ConsoleLogger,
HttpRequestCorrelator,
} from '@villedemontreal/auth-core';
import {
createSession,
createInspector,
IOidcClientConfig,
IOidcSessionConfig,
} from '@villedemontreal/auth-oidc';
import { HttpClientError } from '../../../packages/core/dist';
let requestCounter = 0;
// setup the OIDC configs
const correlator = new HttpRequestCorrelator();
const clientConfig: IOidcClientConfig = {
authMethod: 'client_secret_basic',
client: {
id: 'inspector',
secret: 'inspectorSecret',
},
issuer: 'http://localhost:5000',
scopes: ['openid', 'profile'],
};
const sessionConfig: IOidcSessionConfig = {
scheduleRefresh: true,
factory: {
createLogger: () => new ConsoleLogger(() => correlator.getId()),
},
httpDefaults: {
correlator,
logRequests: false,
},
};
// create the session and the token inspector
const session = createSession(clientConfig, sessionConfig);
const inspector = createInspector(session, {
introspectionEndpointAuthMethod: 'client_secret_basic',
});
// helper functions
function extractToken(header: string) {
const [token_type, access_token] = (header || '').split(' ');
return {
token_type,
access_token,
};
}
// middlewares
function correlationMiddleware(correlator: HttpRequestCorrelator) {
return (
req: express.Request,
res: express.Response,
next: express.NextFunction
) => {
const cid = req.headers['x-correlation-id'] as string;
correlator.withId(next, cid);
};
}
// build the Express app
const app = express();
app.use(correlationMiddleware(correlator));
app.get('/hello', function (req, res) {
res.send('World');
});
app.get('/secured/profile', async function (req, res, next) {
requestCounter += 1;
try {
// if the request has no authorization, return a 401
if (!req.headers.authorization) {
res.sendStatus(401);
return;
}
// get token
const { access_token } = extractToken(req.headers.authorization);
// Note that using the inspector like this is not optimal (no caching),
// but we do it just for the demo.
const tokenInfo = await inspector.getTokenInfo(access_token);
// ensure token is active
if (!tokenInfo.active) {
console.log(
`#${requestCounter}, token is inactive, client is "${tokenInfo.client_id}"`
);
res.sendStatus(401);
return;
}
// calc remaining expiration
const expDate = new Date((tokenInfo.exp || 0) * 1000);
const expInSecs = (expDate.getTime() - new Date().getTime()) / 1000;
console.log(
`#${requestCounter}, token is active, client is "${tokenInfo.client_id}", expires in ${expInSecs} secs`
);
// simulate a bad token every 50 requests
if (requestCounter % 50 === 0) {
console.log(
`#${requestCounter}, --------------------< force 401 error >----------------`
);
res.sendStatus(401);
return;
}
// Send valid response
res.json({ firstName: 'John', lastName: 'Doe' });
// Done
} catch (err) {
// if we catch an error raised by the http client used by the inspector,
// then assume that we could not validate the access token and return a 401
if (err instanceof HttpClientError) {
console.error(err.message);
console.error(err.body);
res.sendStatus(401);
} else {
// pass the error to the next middleware
next(err);
}
}
});
// start the app server
app.listen(4004, () => {
console.log(
'server-api listening on port 4004, check http://localhost:4004/hello'
);
});