@bostonuniversity/shibboleth-sp 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getConfigFromEnvironment = void 0;
4
+ const Keys_1 = require("./Keys");
5
+ /**
6
+ * @returns An instance of IConfig whose values are ALL obtained from the environment.
7
+ */
8
+ const getConfigFromEnvironment = () => {
9
+ let { DOMAIN: domain = 'localhost', APP_LOGIN_HEADER: appLoginHeader, APP_LOGOUT_HEADER: appLogoutHeader, APP_AUTHORIZATION: appAuthorization = 'false', ENTITY_ID: entityId, ENTRY_POINT: entryPoint, LOGOUT_URL: logoutUrl, IDP_CERT: idpCert, SAML_CERT: cert, SAML_PK: key, JWT_PRIVATE_KEY_PEM: jwtPrivateKeyPEM, JWT_PUBLIC_KEY_PEM: jwtPublicKeyPEM } = process.env;
10
+ // If JWT keys are not in the environment, then generate them.
11
+ if (!jwtPrivateKeyPEM && !jwtPublicKeyPEM) {
12
+ const { privateKeyPEM, publicKeyPEM } = new Keys_1.Keys();
13
+ jwtPrivateKeyPEM = privateKeyPEM;
14
+ jwtPublicKeyPEM = publicKeyPEM;
15
+ }
16
+ return {
17
+ domain, appLoginHeader, appLogoutHeader, jwtPrivateKeyPEM, jwtPublicKeyPEM,
18
+ appAuthorization: `${appAuthorization}`.toLowerCase() == 'false' ? false : true,
19
+ samlParms: {
20
+ entityId, entryPoint, logoutUrl, idpCert, cert, key
21
+ }
22
+ };
23
+ };
24
+ exports.getConfigFromEnvironment = getConfigFromEnvironment;
25
+ //# sourceMappingURL=Config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Config.js","sourceRoot":"","sources":["../../src/Config.ts"],"names":[],"mappings":";;;AACA,iCAA8B;AA2B9B;;GAEG;AACI,MAAM,wBAAwB,GAAG,GAAG,EAAE;IAC3C,IAAI,EACF,MAAM,EAAC,MAAM,GAAC,WAAW,EACzB,gBAAgB,EAAC,cAAc,EAC/B,iBAAiB,EAAC,eAAe,EACjC,iBAAiB,EAAC,gBAAgB,GAAC,OAAO,EAC1C,SAAS,EAAC,QAAQ,EAClB,WAAW,EAAC,UAAU,EACtB,UAAU,EAAC,SAAS,EACpB,QAAQ,EAAC,OAAO,EAChB,SAAS,EAAC,IAAI,EACd,OAAO,EAAC,GAAG,EACX,mBAAmB,EAAC,gBAAgB,EACpC,kBAAkB,EAAC,eAAe,EACnC,GAAG,OAAO,CAAC,GAAG,CAAC;IAEhB,8DAA8D;IAC9D,IAAI,CAAE,gBAAgB,IAAI,CAAE,eAAe,EAAE;QAC3C,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,IAAI,WAAI,EAAE,CAAC;QACnD,gBAAgB,GAAG,aAAa,CAAC;QACjC,eAAe,GAAG,YAAY,CAAC;KAChC;IAED,OAAO;QACL,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe;QAC1E,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QAC/E,SAAS,EAAE;YACT,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG;SACpD;KACS,CAAC;AACf,CAAC,CAAA;AA9BY,QAAA,wBAAwB,4BA8BpC"}
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.handler = exports.APP_AUTHORIZATION_HEADER_NAME = exports.AUTH_PATHS = void 0;
13
+ const Saml_1 = require("./Saml");
14
+ const Jwt_1 = require("./Jwt");
15
+ const Utils_1 = require("./Utils");
16
+ const Http_1 = require("./Http");
17
+ var AUTH_PATHS;
18
+ (function (AUTH_PATHS) {
19
+ AUTH_PATHS["LOGIN"] = "/login";
20
+ AUTH_PATHS["LOGOUT"] = "/logout";
21
+ AUTH_PATHS["ASSERT"] = "/assert";
22
+ AUTH_PATHS["METADATA"] = "/metadata";
23
+ AUTH_PATHS["FAVICON"] = "/favicon.ico";
24
+ })(AUTH_PATHS || (exports.AUTH_PATHS = AUTH_PATHS = {}));
25
+ exports.APP_AUTHORIZATION_HEADER_NAME = 'app_authorization';
26
+ /**
27
+ * This is the sp "switchboard operator" for origin request traffic. It will perform all saml SP operations for ensuring
28
+ * that the user bears JWT proof of saml authentication, else it drives the authentication flow with the IDP.
29
+ * @param event
30
+ * @returns Promise<IRequest|IResponse>
31
+ * IRequest: Returning the original request (possibly with headers added) - indicates the request is to be
32
+ * forwarded on to the target app.
33
+ * IResponse: Returning an object that indicates an error or redirection - not passing through to the target app.
34
+ */
35
+ const handler = (originRequest, config) => __awaiter(void 0, void 0, void 0, function* () {
36
+ let { domain, appAuthorization, appLoginHeader, appLogoutHeader, samlParms, jwtPrivateKeyPEM, jwtPublicKeyPEM, customHeaders = [] } = config;
37
+ const { querystring, uri } = originRequest;
38
+ const headers = (0, Http_1.Headers)(originRequest);
39
+ const samlTools = new Saml_1.SamlTools(samlParms);
40
+ const relayDomain = `https://${domain}`;
41
+ samlTools.setAssertUrl(`${relayDomain}/assert`);
42
+ const jwtTools = new Jwt_1.JwtTools();
43
+ jwtTools.resetPublicKey(jwtPublicKeyPEM);
44
+ jwtTools.resetPrivateKey(jwtPrivateKeyPEM);
45
+ // Set appAuth. True means that the target app "decides" if authentication is needed (default).
46
+ // False means an assumption that all requests must be authenticated and that is enforced here.
47
+ const customHdr = headers.get(exports.APP_AUTHORIZATION_HEADER_NAME);
48
+ if (customHdr && 'true' == customHdr) {
49
+ appAuthorization = true;
50
+ }
51
+ try {
52
+ let response;
53
+ const qsparms = querystring ? new URLSearchParams(querystring) : null;
54
+ console.log(`uri: ${uri}`);
55
+ console.log(`querystring: ${querystring}`);
56
+ const { LOGIN, LOGOUT, ASSERT, METADATA, FAVICON } = AUTH_PATHS;
57
+ const getAppLoginUrl = () => {
58
+ const relay_state = encodeURIComponent(relayDomain + uri + (querystring ? `?${querystring}` : ''));
59
+ return `${relayDomain}${AUTH_PATHS.LOGIN}?relay_state=${relay_state}`;
60
+ };
61
+ const getAppLogoutUrl = () => `${relayDomain}${AUTH_PATHS.LOGOUT}`;
62
+ switch (uri) {
63
+ case LOGIN:
64
+ console.log('User is not authenticated, initiate SAML authentication...');
65
+ var relayState = decodeURIComponent(qsparms ? qsparms.get('relay_state') || '' : relayDomain);
66
+ const loginUrl = yield samlTools.createLoginRequestUrl(relayState);
67
+ response = {
68
+ status: '302',
69
+ statusDescription: 'Found',
70
+ headers: {
71
+ location: [{ key: 'Location', value: loginUrl }],
72
+ },
73
+ };
74
+ (0, Utils_1.debugPrint)(`response: ${JSON.stringify(response, null, 2)}`);
75
+ break;
76
+ case LOGOUT:
77
+ const target = qsparms ? qsparms.get('target') : null;
78
+ if (target == 'idp') {
79
+ // Second step: logout with the Idp
80
+ const logoutUrl = yield samlTools.createLogoutRequestUrl();
81
+ response = {
82
+ status: '302',
83
+ statusDescription: 'Found',
84
+ headers: {
85
+ location: [{ key: 'Location', value: logoutUrl }],
86
+ },
87
+ };
88
+ (0, Utils_1.debugPrint)(`IDP logout response: ${JSON.stringify(response, null, 2)}`);
89
+ }
90
+ else {
91
+ // First step: invalidate the jwt along with a redirect to come back and logout with the IDP
92
+ response = {
93
+ status: '302',
94
+ statusDescription: 'Found',
95
+ headers: {
96
+ location: [{ key: 'Location', value: `${relayDomain}/logout?target=idp` }],
97
+ }
98
+ };
99
+ jwtTools.setCookieInvalidationInResponse(response);
100
+ (0, Utils_1.debugPrint)(`Local logout response: ${JSON.stringify(response, null, 2)}`);
101
+ }
102
+ break;
103
+ case ASSERT:
104
+ const result = yield samlTools.sendAssert(originRequest);
105
+ const message = `Authentication successful. result: ${JSON.stringify(result, null, 2)}`;
106
+ var { samlAssertResponse, relayState } = result;
107
+ relayState = decodeURIComponent(relayState || relayDomain);
108
+ if (!samlAssertResponse)
109
+ break;
110
+ (0, Utils_1.debugPrint)(message);
111
+ console.log(`relayState: ${relayState}`);
112
+ const redirectUrl = new URL(relayState);
113
+ redirectUrl.searchParams.append('after_auth', 'true');
114
+ response = {
115
+ status: '302',
116
+ statusDescription: 'Found',
117
+ headers: {
118
+ location: [{ key: 'Location', value: redirectUrl.toString() }],
119
+ },
120
+ };
121
+ const cookieValue = {
122
+ sub: samlAssertResponse.user.name_id,
123
+ user: samlAssertResponse.user.attributes
124
+ };
125
+ console.log(`Setting JWT: ${JSON.stringify(cookieValue, null, 2)}`);
126
+ jwtTools.setCookieInResponse(response, cookieValue);
127
+ break;
128
+ case METADATA:
129
+ response = {
130
+ status: '200',
131
+ statusDescription: 'OK',
132
+ body: samlTools.getMetaData(),
133
+ headers: {
134
+ 'content-type': [{ key: 'Content-Type', value: 'application/xml' }],
135
+ },
136
+ };
137
+ break;
138
+ case FAVICON:
139
+ // This path just dirties up logs, so intercept it here and return a blank.
140
+ // Can't seem to get an actual favicon.ico to work from here anyway.
141
+ response = {
142
+ status: '200',
143
+ statusDescription: 'OK',
144
+ };
145
+ break;
146
+ default:
147
+ const afterAuth = decodeURIComponent(qsparms ? qsparms.get('after_auth') || '' : '');
148
+ const validToken = jwtTools.hasValidToken(originRequest);
149
+ if (validToken) {
150
+ // Tokens are valid, so consider the user authenticated and pass through to the origin.
151
+ console.log('Request has valid JWT');
152
+ response = originRequest;
153
+ (0, Http_1.addHeader)(response, 'authenticated', 'true');
154
+ // Send the entire token in a single header
155
+ const userDetails = `${Buffer.from(JSON.stringify(validToken, null, 2)).toString('base64')}`;
156
+ (0, Http_1.addHeader)(response, 'user-details', userDetails);
157
+ // Also send the individual claims in separate headers, as mod_shib would.
158
+ const { user: { eduPersonPrincipalName, buPrincipal, eduPersonAffiliation, eduPersonEntitlement } } = validToken[Jwt_1.JwtTools.TOKEN_NAME];
159
+ (0, Http_1.addHeader)(response, 'eduPersonPrincipalName', eduPersonPrincipalName);
160
+ (0, Http_1.addHeader)(response, 'buPrincipal', buPrincipal);
161
+ (0, Http_1.addHeader)(response, 'eduPersonAffiliation', eduPersonAffiliation.join(';'));
162
+ (0, Http_1.addHeader)(response, 'eduPersonEntitlement', eduPersonEntitlement.join(';'));
163
+ (0, Http_1.addHeader)(response, appLoginHeader, encodeURIComponent(getAppLoginUrl()));
164
+ (0, Http_1.addHeader)(response, appLogoutHeader, encodeURIComponent(getAppLogoutUrl()));
165
+ for (let i = 0; i < customHeaders.length; i++) {
166
+ const { key, value } = customHeaders[i];
167
+ (0, Http_1.addHeader)(response, key, encodeURIComponent(value));
168
+ }
169
+ console.log(`Valid JWT found - passing through to origin: ${JSON.stringify(response, null, 2)}`);
170
+ }
171
+ else if (afterAuth.toLocaleLowerCase() === 'true') {
172
+ // The saml exchange has just taken place, and the user has authenticated with the IDP, yet either
173
+ // the JWT did not make it into a cookie, or the cookie value did not make it into the header of
174
+ // this request. In either case, we don't redirect back to the login path to try again, because this
175
+ // will most likely result in an endless loop. Just terminate with an error.
176
+ response = {
177
+ status: '500',
178
+ statusDescription: 'State Error',
179
+ body: 'Authentication should have resulted in a valid JWT - no valid token found',
180
+ headers: {
181
+ 'content-type': [{ key: 'Content-Type', value: 'text/plain' }],
182
+ }
183
+ };
184
+ console.log(`No valid JWT found after authentication: ${JSON.stringify(response, null, 2)}`);
185
+ }
186
+ else if (appAuthorization) {
187
+ // The application will "decide" if access to it needs to be authenticated or not, so just pass through the request
188
+ response = originRequest;
189
+ (0, Http_1.addHeader)(response, 'authenticated', 'false');
190
+ (0, Http_1.addHeader)(response, 'login', LOGIN);
191
+ (0, Http_1.addHeader)(response, appLoginHeader, encodeURIComponent(getAppLoginUrl()));
192
+ (0, Http_1.addHeader)(response, appLogoutHeader, encodeURIComponent(getAppLogoutUrl()));
193
+ for (let i = 0; i < customHeaders.length; i++) {
194
+ const { key, value } = customHeaders[i];
195
+ (0, Http_1.addHeader)(response, key, encodeURIComponent(value));
196
+ }
197
+ console.log('App will determine need for auth - passing through to origin');
198
+ }
199
+ else {
200
+ // No valid token has been found, and this is not a post authentication redirect - send user to login.
201
+ response = {
202
+ status: '302',
203
+ statusDescription: 'Found',
204
+ headers: {
205
+ location: [{ key: 'Location', value: getAppLoginUrl() }],
206
+ },
207
+ };
208
+ console.log(`No valid JWT found - redirecting: ${JSON.stringify(response, null, 2)}`);
209
+ }
210
+ break;
211
+ }
212
+ return response;
213
+ }
214
+ catch (error) {
215
+ // Handle authentication error
216
+ console.error('SP error:', error);
217
+ return {
218
+ status: '500',
219
+ statusDescription: 'Server Error',
220
+ body: `${JSON.stringify({ message: error.message, stack: error.stack }, null, 2)}`,
221
+ headers: {
222
+ 'content-type': [{ key: 'Content-Type', value: 'text/plain' }],
223
+ // 'www-authenticate': [{ key: 'WWW-Authenticate', value: 'Basic' }],
224
+ },
225
+ };
226
+ }
227
+ });
228
+ exports.handler = handler;
229
+ //# sourceMappingURL=HandlerSp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HandlerSp.js","sourceRoot":"","sources":["../../src/HandlerSp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getHost = exports.addHeader = exports.Headers = void 0;
4
+ const Utils_1 = require("./Utils");
5
+ /**
6
+ * Header accessor wrapper.
7
+ * @param request
8
+ * @returns
9
+ */
10
+ const Headers = (request) => {
11
+ const { headers } = request;
12
+ if (headers) {
13
+ const get = (key) => {
14
+ if (!key) {
15
+ return null;
16
+ }
17
+ if (headers[key.toLowerCase()]) {
18
+ return headers[key.toLowerCase()][0].value;
19
+ }
20
+ return null;
21
+ };
22
+ const join = (joiner, except = []) => {
23
+ return Object.keys(headers).map(key => {
24
+ return `${key}: ${get(key)}`;
25
+ })
26
+ .filter(key => {
27
+ return except.find(e => {
28
+ return e.toLowerCase() == key.toLowerCase();
29
+ }) == undefined;
30
+ })
31
+ .join(joiner);
32
+ };
33
+ const isTruthy = (key) => {
34
+ return `${get(key)}`.toLowerCase() == 'true';
35
+ };
36
+ return { empty: false, get, join, isTruthy };
37
+ }
38
+ return { empty: true, get: () => null, join: () => '', isTruthy: () => false };
39
+ };
40
+ exports.Headers = Headers;
41
+ /**
42
+ * Utility function for adding headers to a request or response
43
+ * @param obj
44
+ * @param keyname
45
+ * @param value
46
+ * @returns
47
+ */
48
+ const addHeader = (obj, keyname, value) => {
49
+ const { isBlank } = Utils_1.ParameterTester;
50
+ if (isBlank(value)) {
51
+ console.log(`ERROR: attempt to set header ${keyname} with "${value}"`);
52
+ return;
53
+ }
54
+ if (obj.headers) {
55
+ obj.headers[keyname.toLowerCase()] = [{ key: keyname, value }];
56
+ if ((0, Utils_1.instanceOf)(obj, "uri")) {
57
+ // Be more specific as to header activity when it comes to IRequest instances
58
+ obj.headerActivity.added[keyname.toLowerCase()] = [{ key: keyname, value }];
59
+ }
60
+ }
61
+ };
62
+ exports.addHeader = addHeader;
63
+ /**
64
+ * Extracts the host header value from an HTTP request.
65
+ * @param request The HTTP request object
66
+ * @returns The host header value, or null if not found or invalid request
67
+ */
68
+ const getHost = (request) => {
69
+ if (!request || !request.headers) {
70
+ return null;
71
+ ;
72
+ }
73
+ try {
74
+ const headers = (0, exports.Headers)(request);
75
+ return headers.get('host');
76
+ }
77
+ catch (e) {
78
+ console.log(`ERROR: Unable to determine host from request: ${JSON.stringify(request, null, 2)}`);
79
+ }
80
+ return null;
81
+ };
82
+ exports.getHost = getHost;
83
+ //# sourceMappingURL=Http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Http.js","sourceRoot":"","sources":["../../src/Http.ts"],"names":[],"mappings":";;;AAAA,mCAAsD;AA4DtD;;;;GAIG;AACI,MAAM,OAAO,GAAG,CAAC,OAA0B,EAAW,EAAE;IAC7D,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,IAAG,OAAO,EAAE;QACV,MAAM,GAAG,GAAG,CAAC,GAAyB,EAAc,EAAE;YACpD,IAAG,CAAC,GAAG,EAAE;gBACP,OAAO,IAAI,CAAC;aACb;YACD,IAAG,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE;gBAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;aAC5C;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAA;QACD,MAAM,IAAI,GAAG,CAAC,MAAa,EAAE,SAAgB,EAAE,EAAS,EAAE;YACxD,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;gBACpC,OAAO,GAAG,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,EAAE,CAAA;YAC9B,CAAC,CAAC;iBACD,MAAM,CAAC,GAAG,CAAC,EAAE;gBACZ,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;oBACrB,OAAO,CAAC,CAAC,WAAW,EAAE,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBAC9C,CAAC,CAAC,IAAI,SAAS,CAAC;YAClB,CAAC,CAAC;iBACD,IAAI,CAAC,MAAM,CAAC,CAAC;QAChB,CAAC,CAAA;QACD,MAAM,QAAQ,GAAG,CAAC,GAAU,EAAU,EAAE;YACtC,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC;QAC/C,CAAC,CAAA;QACD,OAAO,EAAE,KAAK,EAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;KAC7C;IACD,OAAO,EAAE,KAAK,EAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;AAChF,CAAC,CAAA;AA7BY,QAAA,OAAO,WA6BnB;AAED;;;;;;GAMG;AACI,MAAM,SAAS,GAAG,CAAC,GAAsB,EAAE,OAAc,EAAE,KAAY,EAAE,EAAE;IAChF,MAAM,EAAE,OAAO,EAAE,GAAG,uBAAe,CAAC;IACpC,IAAG,OAAO,CAAC,KAAK,CAAC,EAAE;QACjB,OAAO,CAAC,GAAG,CAAC,gCAAgC,OAAO,UAAU,KAAK,GAAG,CAAC,CAAC;QACvE,OAAO;KACR;IACD,IAAG,GAAG,CAAC,OAAO,EAAE;QACd,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,IAAG,IAAA,kBAAU,EAAW,GAAG,EAAE,KAAK,CAAC,EAAE;YACnC,6EAA6E;YAC7E,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;SAC7E;KACF;AACH,CAAC,CAAA;AAbY,QAAA,SAAS,aAarB;AAID;;;;GAIG;AACI,MAAM,OAAO,GAAG,CAAC,OAAgB,EAAc,EAAE;IACtD,IAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;QAC/B,OAAO,IAAI,CAAC;QAAA,CAAC;KACd;IACD,IAAI;QACF,MAAM,OAAO,GAAG,IAAA,eAAO,EAAC,OAAO,CAAC,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;KAC5B;IACD,OAAM,CAAK,EAAE;QACX,OAAO,CAAC,GAAG,CAAC,iDAAiD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;KAClG;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAA;AAZY,QAAA,OAAO,WAYnB"}
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.JwtTools = void 0;
30
+ const jwt = __importStar(require("jsonwebtoken"));
31
+ const ms_1 = __importDefault(require("ms"));
32
+ /**
33
+ * Use the jsonwebtoken library to create and verify jwts.
34
+ *
35
+ * @see https://www.npmjs.com/package/jsonwebtoken
36
+ */
37
+ class JwtTools {
38
+ constructor() {
39
+ this.expiresIn = '7d';
40
+ }
41
+ resetPrivateKey(privateKey) {
42
+ this.privateKey = privateKey;
43
+ }
44
+ resetPublicKey(publicKey) {
45
+ this.publicKey = publicKey;
46
+ }
47
+ setExpiration(expiresIn) {
48
+ this.expiresIn = expiresIn;
49
+ }
50
+ setClockTime(clockTime) {
51
+ this.clockTime = clockTime;
52
+ }
53
+ /**
54
+ * The cookie header is a concatenation of name=value pairs delimited by a ";" character.
55
+ * Get the value of one of these pairs, specified by name.
56
+ * @param request The HTTP request containing cookies
57
+ * @param cookieName The name of the cookie to retrieve
58
+ * @returns The cookie value if found, undefined otherwise
59
+ */
60
+ parseCookieValue(request, cookieName) {
61
+ let { cookie: cookieHeader } = request.headers;
62
+ if (cookieHeader) {
63
+ let cookieHdrVal;
64
+ if (typeof cookieHeader != 'string') {
65
+ cookieHdrVal = cookieHeader[0].value;
66
+ }
67
+ const cookies = cookieHdrVal ? cookieHdrVal.split(';') : [];
68
+ for (const cookie of cookies) {
69
+ const [name, value] = cookie.trim().split('=');
70
+ if (name === cookieName) {
71
+ return value;
72
+ }
73
+ }
74
+ }
75
+ return null;
76
+ }
77
+ /**
78
+ * Any environment variable starting with "IMPERSONATE_" is treated as an attribute for building a jwt token.
79
+ * This provides an option for mocking a jwt while running locally for testing so as to "pretend" a valid jwt
80
+ * was provided with the http request.
81
+ * @example
82
+ * IMPERSONATE_buPrincipal=wrh
83
+ * IMPERSONATE_eduPersonPrincipalName=wrh@bu.edu
84
+ * IMPERSONATE_eduPersonAffiliation=employee|member|staff
85
+ * @returns JWT token object with impersonation attributes, or null if no IMPERSONATE_ environment variables are found
86
+ */
87
+ getImpersonationToken() {
88
+ let sub = '';
89
+ const attributes = {};
90
+ Object.keys(process.env).filter((e) => {
91
+ return e.toLocaleUpperCase().startsWith('IMPERSONATE_') ? e : null;
92
+ }).forEach((e) => {
93
+ const attributeValue = process.env[e];
94
+ const attributeName = e.substring(e.indexOf('_') + 1);
95
+ if (attributeName.toLocaleLowerCase() === 'name_id') {
96
+ sub = attributeValue;
97
+ }
98
+ else {
99
+ attributes[attributeName] = attributeValue.split('|').map((e) => { return e.trim(); });
100
+ }
101
+ });
102
+ if (Object.keys(attributes).length > 0) {
103
+ const retval = {
104
+ [JwtTools.TOKEN_NAME]: { sub, user: { attributes } }
105
+ };
106
+ return retval;
107
+ }
108
+ return null;
109
+ }
110
+ /**
111
+ * Extract the decoded JWT from the larger cookie value.
112
+ * @param request
113
+ * @param verify
114
+ * @returns
115
+ */
116
+ getToken(request, verify) {
117
+ try {
118
+ const impersonationToken = this.getImpersonationToken();
119
+ if (impersonationToken) {
120
+ return impersonationToken;
121
+ }
122
+ const { cookie } = request.headers;
123
+ if (cookie) {
124
+ let authToken = this.parseCookieValue(request, JwtTools.COOKIE_NAME);
125
+ if (authToken) {
126
+ let decoded;
127
+ if (verify) {
128
+ decoded = jwt.verify(authToken, this.publicKey, {
129
+ algorithms: ['RS256'],
130
+ clockTimestamp: this.clockTime
131
+ });
132
+ }
133
+ else {
134
+ decoded = jwt.decode(authToken);
135
+ }
136
+ // If no error is thrown, then the token is valid
137
+ return decoded;
138
+ }
139
+ }
140
+ return null;
141
+ }
142
+ catch (error) {
143
+ return null;
144
+ }
145
+ }
146
+ /**
147
+ * Determine if a request carries a valid jwt in its cookie header.
148
+ * @param request
149
+ * @returns
150
+ */
151
+ hasValidToken(request) {
152
+ return this.getToken(request, true);
153
+ }
154
+ /**
155
+ * Place a jwt in a "set-cookie" response header.
156
+ * @param response
157
+ * @param payload
158
+ */
159
+ setCookieInResponse(response, payload) {
160
+ const jwtToken = jwt.sign({ [JwtTools.TOKEN_NAME]: payload }, this.privateKey, {
161
+ algorithm: 'RS256',
162
+ expiresIn: this.expiresIn,
163
+ });
164
+ const maxAge = Math.floor((0, ms_1.default)(this.expiresIn) / 1000);
165
+ response.headers['set-cookie'] = [{
166
+ key: 'Set-Cookie',
167
+ value: `${JwtTools.COOKIE_NAME}=${jwtToken}; Max-Age=${maxAge}; Secure; HttpOnly`
168
+ }];
169
+ }
170
+ setCookieInvalidationInResponse(response) {
171
+ response.headers['set-cookie'] = [{
172
+ key: 'Set-Cookie',
173
+ value: `${JwtTools.COOKIE_NAME}=invalidated; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly`
174
+ }];
175
+ }
176
+ getCookieName() {
177
+ return JwtTools.COOKIE_NAME;
178
+ }
179
+ getTokenName() {
180
+ return JwtTools.TOKEN_NAME;
181
+ }
182
+ }
183
+ exports.JwtTools = JwtTools;
184
+ JwtTools.TOKEN_NAME = 'auth-token';
185
+ JwtTools.COOKIE_NAME = `${JwtTools.TOKEN_NAME}-cookie`;
186
+ //# sourceMappingURL=Jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Jwt.js","sourceRoot":"","sources":["../../src/Jwt.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAoC;AACpC,4CAAqC;AAGrC;;;;GAIG;AACH,MAAa,QAAQ;IAArB;QAIU,cAAS,GAAe,IAAI,CAAC;IAgKvC,CAAC;IA1JQ,eAAe,CAAC,UAAiB;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IACM,cAAc,CAAC,SAAgB;QACpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IACM,aAAa,CAAC,SAAgB;QACnC,IAAI,CAAC,SAAS,GAAG,SAAwB,CAAC;IAC5C,CAAC;IACM,YAAY,CAAC,SAAgB;QAClC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;;;;;OAMG;IACI,gBAAgB,CAAC,OAAgB,EAAE,UAAiB;QACzD,IAAI,EAAE,MAAM,EAAC,YAAY,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;QAC9C,IAAG,YAAY,EAAE;YACf,IAAI,YAA6B,CAAC;YAClC,IAAG,OAAO,YAAY,IAAI,QAAQ,EAAE;gBAClC,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;aACtC;YACD,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,KAAI,MAAM,MAAM,IAAI,OAAO,EAAE;gBAC3B,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC/C,IAAI,IAAI,KAAK,UAAU,EAAE;oBACvB,OAAO,KAAK,CAAC;iBACd;aACF;SACF;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;OASG;IACI,qBAAqB;QAC1B,IAAI,GAAG,GAAU,EAAE,CAAC;QACpB,MAAM,UAAU,GAAG,EAAU,CAAC;QAE9B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,OAAO,CAAC,CAAC,iBAAiB,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACf,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAW,CAAC;YAChD,MAAM,aAAa,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAC,CAAC,CAAC,CAAC;YACpD,IAAG,aAAa,CAAC,iBAAiB,EAAE,KAAK,SAAS,EAAE;gBAClD,GAAG,GAAG,cAAc,CAAC;aACtB;iBACI;gBACH,UAAU,CAAC,aAAa,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA,CAAA,CAAC,CAAC,CAAC;aACtF;QACH,CAAC,CAAC,CAAC;QAEH,IAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YACrC,MAAM,MAAM,GAAG;gBACb,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,UAAU,EAAC,EAAE;aACpD,CAAC;YACF,OAAO,MAAM,CAAC;SACf;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACI,QAAQ,CAAC,OAAgB,EAAE,MAAe;QAC/C,IAAI;YACF,MAAM,kBAAkB,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACxD,IAAG,kBAAkB,EAAE;gBACrB,OAAO,kBAAkB,CAAC;aAC3B;YACD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;YACnC,IAAG,MAAM,EAAE;gBACT,IAAI,SAAS,GAAe,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;gBACjF,IAAG,SAAS,EAAE;oBACZ,IAAI,OAAW,CAAC;oBAChB,IAAG,MAAM,EAAE;wBACT,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;4BAC9C,UAAU,EAAE,CAAC,OAAO,CAAC;4BACrB,cAAc,EAAE,IAAI,CAAC,SAAS;yBAC/B,CAAC,CAAC;qBACJ;yBACI;wBACH,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;qBACjC;oBAED,iDAAiD;oBACjD,OAAO,OAAO,CAAC;iBAChB;aACF;YACD,OAAO,IAAI,CAAC;SACb;QACD,OAAO,KAAK,EAAE;YACZ,OAAO,IAAI,CAAC;SACb;IACH,CAAC;IAED;;;;OAIG;IACI,aAAa,CAAC,OAAgB;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACI,mBAAmB,CAAC,QAAY,EAAE,OAAW;QAClD,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE;YAC7E,SAAS,EAAE,OAAO;YAClB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,YAAE,EAAC,IAAI,CAAC,SAAS,CAAC,GAAC,IAAI,CAAC,CAAC;QACnD,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC;gBAChC,GAAG,EAAE,YAAY;gBACjB,KAAK,EAAE,GAAG,QAAQ,CAAC,WAAW,IAAI,QAAQ,aAAa,MAAM,oBAAoB;aAClF,CAAC,CAAC;IACL,CAAC;IAEM,+BAA+B,CAAC,QAAY;QACjD,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC;gBAChC,GAAG,EAAE,YAAY;gBACjB,KAAK,EAAE,GAAG,QAAQ,CAAC,WAAW,kFAAkF;aACjH,CAAC,CAAC;IACL,CAAC;IAEM,aAAa;QAClB,OAAO,QAAQ,CAAC,WAAW,CAAC;IAC9B,CAAC;IACM,YAAY;QACjB,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC7B,CAAC;;AAnKH,4BAoKC;AA7Je,mBAAU,GAAU,YAAY,AAAtB,CAAuB;AACjC,oBAAW,GAAU,GAAG,QAAQ,CAAC,UAAU,SAAS,AAAzC,CAA0C"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.Keys = void 0;
27
+ const forge = __importStar(require("node-forge"));
28
+ class Keys {
29
+ constructor() {
30
+ this.extractValueFromPEM = (pem) => {
31
+ return pem.replace(/[\r\n]/g, '').split(/\-{2,}/)[2];
32
+ };
33
+ this.toString = () => {
34
+ return JSON.stringify({
35
+ privateKey: this.privateKey,
36
+ publicKey: this.publicKey,
37
+ certificate: this.certificate
38
+ }, null, 2);
39
+ };
40
+ const keys = forge.pki.rsa.generateKeyPair(2048);
41
+ const cert = forge.pki.createCertificate();
42
+ const yearsToExpire = 5;
43
+ cert.publicKey = keys.publicKey;
44
+ cert.serialNumber = '01';
45
+ cert.validity.notBefore = new Date();
46
+ cert.validity.notAfter = new Date();
47
+ cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + yearsToExpire);
48
+ const attrs = [
49
+ { name: 'commonName', value: 'example.org' },
50
+ { name: 'countryName', value: 'US' },
51
+ { shortName: 'ST', value: 'Massachusetts' },
52
+ { name: 'localityName', value: 'Boston' },
53
+ { name: 'organizationName', value: 'Boston University' },
54
+ { shortName: 'OU', value: 'Test' }
55
+ ];
56
+ cert.setSubject(attrs);
57
+ cert.setIssuer(attrs);
58
+ cert.sign(keys.privateKey);
59
+ this._keys = keys;
60
+ this._certificate = cert;
61
+ }
62
+ get privateKey() {
63
+ return this.extractValueFromPEM(this.privateKeyPEM);
64
+ }
65
+ get publicKey() {
66
+ return this.extractValueFromPEM(this.publicKeyPEM);
67
+ }
68
+ get certificate() {
69
+ return this.extractValueFromPEM(this.certificatePEM);
70
+ }
71
+ get privateKeyPEM() {
72
+ return forge.pki.privateKeyToPem(this._keys.privateKey);
73
+ }
74
+ get publicKeyPEM() {
75
+ return forge.pki.publicKeyToPem(this._keys.publicKey);
76
+ }
77
+ get certificatePEM() {
78
+ return forge.pki.certificateToPem(this._certificate);
79
+ }
80
+ }
81
+ exports.Keys = Keys;
82
+ //# sourceMappingURL=Keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Keys.js","sourceRoot":"","sources":["../../src/Keys.ts"],"names":[],"mappings":"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"}