@oslokommune/auth-bff 1.5.1 → 1.6.0-beta1
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.
- package/dist/middleware/oidc-routes.d.mts.map +1 -1
- package/dist/middleware/oidc-routes.mjs +1 -0
- package/dist/middleware/oidc.d.mts +1 -0
- package/dist/middleware/oidc.d.mts.map +1 -1
- package/dist/middleware/oidc.mjs +28 -8
- package/dist/middleware/sessions.d.mts +1 -1
- package/dist/middleware/sessions.d.mts.map +1 -1
- package/dist/middleware/sessions.mjs +68 -16
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +3 -0
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc-routes.d.mts","sourceRoot":"","sources":["../../src/middleware/oidc-routes.mjs"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"oidc-routes.d.mts","sourceRoot":"","sources":["../../src/middleware/oidc-routes.mjs"],"names":[],"mappings":"AAEA,qDAUC"}
|
|
@@ -5,5 +5,6 @@ export function oidcRoutes(oidcMiddleware) {
|
|
|
5
5
|
router.get('/auth/callback', oidcMiddleware.callback);
|
|
6
6
|
router.get('/auth/logout', oidcMiddleware.logout);
|
|
7
7
|
router.get('/auth/user', oidcMiddleware.user);
|
|
8
|
+
router.get('/auth/front-channel-logout', oidcMiddleware.frontChannelLogout);
|
|
8
9
|
return router;
|
|
9
10
|
}
|
|
@@ -11,6 +11,7 @@ export class OidcMiddleware {
|
|
|
11
11
|
get callback(): (req: any, res: any, next: any) => Promise<void>;
|
|
12
12
|
get user(): (req: any, res: any, next: any) => Promise<any>;
|
|
13
13
|
get logout(): (req: any, res: any) => void;
|
|
14
|
+
get frontChannelLogout(): (req: any, res: any) => Promise<void>;
|
|
14
15
|
#private;
|
|
15
16
|
}
|
|
16
17
|
//# sourceMappingURL=oidc.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc.d.mts","sourceRoot":"","sources":["../../src/middleware/oidc.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"oidc.d.mts","sourceRoot":"","sources":["../../src/middleware/oidc.mjs"],"names":[],"mappings":"AAIA;IAeE,oDAIC;IAdD;;;;OAIG;IACH,sBAGC;IAsDD,yBACU,QAAG,EAAE,QAAG,EAAE,SAAI,UAWvB;IAED,cACU,QAAG,EAAE,QAAG,UAsBjB;IAED,iBACgB,QAAG,EAAE,QAAG,EAAE,SAAI,mBAqC7B;IAED,aACgB,QAAG,EAAE,QAAG,EAAE,SAAI,kBAmB7B;IAED,eACU,QAAG,EAAE,QAAG,UAQjB;IAED,2BACgB,QAAG,EAAE,QAAG,mBAcvB;;CACF"}
|
package/dist/middleware/oidc.mjs
CHANGED
|
@@ -21,6 +21,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
21
21
|
var _OidcMiddleware_instances, _OidcMiddleware_clientManager, _OidcMiddleware_config, _OidcMiddleware_refreshPromises, _OidcMiddleware_refreshTokenSet, _OidcMiddleware_getFreshTokenSet;
|
|
22
22
|
import { generators, TokenSet } from "openid-client";
|
|
23
23
|
import { OidcClientManager } from "../client.mjs";
|
|
24
|
+
import { redact } from "../utils.js";
|
|
24
25
|
export class OidcMiddleware {
|
|
25
26
|
/**
|
|
26
27
|
* @private
|
|
@@ -56,6 +57,7 @@ export class OidcMiddleware {
|
|
|
56
57
|
next();
|
|
57
58
|
}
|
|
58
59
|
else {
|
|
60
|
+
console.warn(`401: No valid tokenSet in session sid=${redact(req.session.id)}`);
|
|
59
61
|
res.sendStatus(401);
|
|
60
62
|
}
|
|
61
63
|
}).catch(next);
|
|
@@ -92,7 +94,9 @@ export class OidcMiddleware {
|
|
|
92
94
|
code_verifier: codeVerifier,
|
|
93
95
|
state: stateKey
|
|
94
96
|
});
|
|
95
|
-
req.session.tokenSet =
|
|
97
|
+
req.session.tokenSet = tokenSet;
|
|
98
|
+
const parsedTokenSet = new TokenSet(tokenSet);
|
|
99
|
+
req.session["idp-sid"] = parsedTokenSet.claims().sid;
|
|
96
100
|
delete req.session.codeVerifier;
|
|
97
101
|
delete req.session.stateKey;
|
|
98
102
|
delete req.session.stateValue;
|
|
@@ -132,7 +136,7 @@ export class OidcMiddleware {
|
|
|
132
136
|
return res.send(claims);
|
|
133
137
|
}
|
|
134
138
|
catch (e) {
|
|
135
|
-
console.error(`Error in /user sid=${(_a = req.session) === null || _a === void 0 ? void 0 : _a.id}`, e
|
|
139
|
+
console.error(`Error in /user sid=${redact((_a = req.session) === null || _a === void 0 ? void 0 : _a.id)}`, e);
|
|
136
140
|
next(e);
|
|
137
141
|
}
|
|
138
142
|
});
|
|
@@ -140,7 +144,6 @@ export class OidcMiddleware {
|
|
|
140
144
|
get logout() {
|
|
141
145
|
return (req, res) => {
|
|
142
146
|
const tokenSet = req.session.tokenSet && new TokenSet(req.session.tokenSet);
|
|
143
|
-
//TODO: støtt frontchannel SLO
|
|
144
147
|
req.session.destroy(() => {
|
|
145
148
|
res.redirect(__classPrivateFieldGet(this, _OidcMiddleware_clientManager, "f").client.endSessionUrl({
|
|
146
149
|
id_token_hint: tokenSet === null || tokenSet === void 0 ? void 0 : tokenSet.id_token,
|
|
@@ -148,6 +151,22 @@ export class OidcMiddleware {
|
|
|
148
151
|
});
|
|
149
152
|
};
|
|
150
153
|
}
|
|
154
|
+
get frontChannelLogout() {
|
|
155
|
+
return (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
var _a;
|
|
157
|
+
const { iss, sid } = req.query;
|
|
158
|
+
console.log(`Front channel logout: params iss=${iss}, sid=${redact(sid)}`);
|
|
159
|
+
if (sid) {
|
|
160
|
+
try {
|
|
161
|
+
yield ((_a = req.destroySessionByIdTokenSid) === null || _a === void 0 ? void 0 : _a.call(req, sid));
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
console.error("Failed to destroy session", e);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
res.sendStatus(200);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
151
170
|
}
|
|
152
171
|
_OidcMiddleware_clientManager = new WeakMap(), _OidcMiddleware_config = new WeakMap(), _OidcMiddleware_refreshPromises = new WeakMap(), _OidcMiddleware_instances = new WeakSet(), _OidcMiddleware_refreshTokenSet = function _OidcMiddleware_refreshTokenSet(req, tokenSet) {
|
|
153
172
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -156,19 +175,19 @@ _OidcMiddleware_clientManager = new WeakMap(), _OidcMiddleware_config = new Weak
|
|
|
156
175
|
const sessionId = req.session.id;
|
|
157
176
|
const refreshToken = tokenSet.refresh_token;
|
|
158
177
|
const doRefresh = () => __awaiter(this, void 0, void 0, function* () {
|
|
159
|
-
console.log(`Token refresh starting. sid=${sessionId}`);
|
|
178
|
+
console.log(`Token refresh starting. sid=${redact(sessionId)}`);
|
|
160
179
|
try {
|
|
161
180
|
const refreshedTokenSet = yield __classPrivateFieldGet(this, _OidcMiddleware_clientManager, "f").client.refresh(refreshToken);
|
|
162
|
-
console.log(`Token refresh OK. sid=${sessionId}`);
|
|
181
|
+
console.log(`Token refresh OK. sid=${redact(sessionId)}`);
|
|
163
182
|
return refreshedTokenSet;
|
|
164
183
|
}
|
|
165
184
|
catch (err) {
|
|
166
|
-
console.log(`Token refresh failed. sid=${sessionId}`, err);
|
|
185
|
+
console.log(`Token refresh failed. sid=${redact(sessionId)}`, err);
|
|
167
186
|
return null;
|
|
168
187
|
}
|
|
169
188
|
});
|
|
170
189
|
const refreshPromise = (_a = (_b = __classPrivateFieldGet(this, _OidcMiddleware_refreshPromises, "f"))[refreshToken]) !== null && _a !== void 0 ? _a : (_b[refreshToken] = doRefresh().finally(() => {
|
|
171
|
-
console.log(`Token refresh finished. Cleaning up. sid=${sessionId}`);
|
|
190
|
+
console.log(`Token refresh finished. Cleaning up. sid=${redact(sessionId)}`);
|
|
172
191
|
setTimeout(() => {
|
|
173
192
|
delete __classPrivateFieldGet(this, _OidcMiddleware_refreshPromises, "f")[refreshToken];
|
|
174
193
|
}, 10000);
|
|
@@ -186,10 +205,11 @@ _OidcMiddleware_clientManager = new WeakMap(), _OidcMiddleware_config = new Weak
|
|
|
186
205
|
return __awaiter(this, void 0, void 0, function* () {
|
|
187
206
|
const tokenSet = req.session.tokenSet && new TokenSet(req.session.tokenSet);
|
|
188
207
|
if (!tokenSet) {
|
|
189
|
-
console.log(
|
|
208
|
+
console.log(`No tokenSet found in session sid=${redact(req.session.id)}`);
|
|
190
209
|
return;
|
|
191
210
|
}
|
|
192
211
|
if (tokenSet.expired()) {
|
|
212
|
+
console.log(`TokenSet expired sid=${redact(req.session.id)}`);
|
|
193
213
|
const newTokenSet = yield __classPrivateFieldGet(this, _OidcMiddleware_instances, "m", _OidcMiddleware_refreshTokenSet).call(this, req, tokenSet);
|
|
194
214
|
return newTokenSet && new TokenSet(newTokenSet);
|
|
195
215
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export function sessions(config: any): any;
|
|
1
|
+
export function sessions(config: any): any[];
|
|
2
2
|
//# sourceMappingURL=sessions.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.mts","sourceRoot":"","sources":["../../src/middleware/sessions.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sessions.d.mts","sourceRoot":"","sources":["../../src/middleware/sessions.mjs"],"names":[],"mappings":"AAiDA,6CAgCC"}
|
|
@@ -1,17 +1,63 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
import session from "express-session";
|
|
2
11
|
import dynamoDbStore from "connect-dynamodb";
|
|
12
|
+
import { DeleteItemCommand, DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
|
|
13
|
+
import { redact } from "../utils.js";
|
|
3
14
|
function dynamoDbSessionStore(config = {}) {
|
|
15
|
+
const client = new DynamoDBClient({});
|
|
4
16
|
const DynamoDbStore = dynamoDbStore({ session });
|
|
5
|
-
|
|
17
|
+
const sessionStoreConfig = Object.assign(Object.assign({}, config), { client, specialKeys: [
|
|
18
|
+
{ name: "idp-sid", type: "S" }
|
|
19
|
+
], skipThrowMissingSpecialKeys: true });
|
|
20
|
+
const sessionStore = new DynamoDbStore(sessionStoreConfig);
|
|
21
|
+
sessionStore.destroyByIdTokenSid = (idTokenSid) => __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
console.log(`Front channel logout: deleting session(s) with idp-sid=${redact(idTokenSid)}`);
|
|
23
|
+
const query = new QueryCommand({
|
|
24
|
+
TableName: config.table,
|
|
25
|
+
IndexName: "idp-sid-index",
|
|
26
|
+
ExpressionAttributeValues: { ":sid": { S: idTokenSid } },
|
|
27
|
+
ExpressionAttributeNames: { "#k": "idp-sid" },
|
|
28
|
+
KeyConditionExpression: "#k = :sid",
|
|
29
|
+
ProjectionExpression: "id"
|
|
30
|
+
});
|
|
31
|
+
const res = yield client.send(query);
|
|
32
|
+
yield Promise.all(res.Items.map((item) => {
|
|
33
|
+
var _a;
|
|
34
|
+
console.log(`Front channel logout: deleting session ${redact((_a = item.id) === null || _a === void 0 ? void 0 : _a.S, 10)}`);
|
|
35
|
+
return client.send(new DeleteItemCommand({
|
|
36
|
+
TableName: config.table,
|
|
37
|
+
Key: { id: item.id }
|
|
38
|
+
}));
|
|
39
|
+
}));
|
|
40
|
+
console.log(`Front channel logout: completed. ${res.Count} session(s) deleted`);
|
|
41
|
+
});
|
|
42
|
+
return sessionStore;
|
|
43
|
+
}
|
|
44
|
+
function memorySessionStore(config = {}) {
|
|
45
|
+
const sessionStore = new session.MemoryStore(config);
|
|
46
|
+
sessionStore.destroyByIdTokenSid = (idTokenSid) => {
|
|
47
|
+
// dummy.
|
|
48
|
+
console.log(`Pretending to destroyByIdTokenSid. idp-sid=${redact(idTokenSid)}`);
|
|
49
|
+
};
|
|
50
|
+
return sessionStore;
|
|
6
51
|
}
|
|
7
52
|
export function sessions(config) {
|
|
8
|
-
var _a;
|
|
53
|
+
var _a, _b;
|
|
9
54
|
let sessionStore;
|
|
10
55
|
if (config.sessionStoreType === 'memory') {
|
|
11
|
-
|
|
56
|
+
const sessionStoreOptions = (_a = config.sessionStoreOptions) !== null && _a !== void 0 ? _a : {};
|
|
57
|
+
sessionStore = memorySessionStore(sessionStoreOptions);
|
|
12
58
|
}
|
|
13
59
|
else if (config.sessionStoreType === 'dynamodb') {
|
|
14
|
-
const sessionStoreOptions = (
|
|
60
|
+
const sessionStoreOptions = (_b = config.sessionStoreOptions) !== null && _b !== void 0 ? _b : {};
|
|
15
61
|
sessionStore = dynamoDbSessionStore(sessionStoreOptions);
|
|
16
62
|
}
|
|
17
63
|
else if (config.sessionStoreType) {
|
|
@@ -20,16 +66,22 @@ export function sessions(config) {
|
|
|
20
66
|
else {
|
|
21
67
|
throw Error('missing sessionStoreType');
|
|
22
68
|
}
|
|
23
|
-
return
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
69
|
+
return [
|
|
70
|
+
session({
|
|
71
|
+
secret: config.sessionSecret,
|
|
72
|
+
store: sessionStore,
|
|
73
|
+
resave: false,
|
|
74
|
+
saveUninitialized: false,
|
|
75
|
+
cookie: config.cookie || {
|
|
76
|
+
httpOnly: true,
|
|
77
|
+
path: config.cookiePath,
|
|
78
|
+
secure: config.cookieSecure,
|
|
79
|
+
sameSite: config.cookieSameSite
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
(req) => {
|
|
83
|
+
// make this function available to request handlers
|
|
84
|
+
req.destroySessionByIdTokenSid = sessionStore === null || sessionStore === void 0 ? void 0 : sessionStore.destroyByIdTokenSid;
|
|
85
|
+
}
|
|
86
|
+
];
|
|
35
87
|
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.js"],"names":[],"mappings":"AAAA,6DAEC"}
|
package/dist/utils.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oslokommune/auth-bff",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0-beta1",
|
|
4
4
|
"repository": "https://github.com/oslokommune/auth-bff.git",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "tsc",
|
|
10
10
|
"run": "node ./dist/server.mjs",
|
|
11
|
-
"build-and-publish": "tsc && npm publish"
|
|
11
|
+
"build-and-publish": "tsc && npm publish",
|
|
12
|
+
"build-and-publish-prerelease": "tsc && npm publish --tag prerelease"
|
|
12
13
|
},
|
|
13
14
|
"exports": {
|
|
14
15
|
"./vite-plugin": "./dist/vite-plugin.mjs",
|