@mongodb-js/oidc-plugin 1.1.7 → 2.0.0
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/api.d.ts +12 -4
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +3 -3
- package/dist/api.js.map +1 -1
- package/dist/log-hook.d.ts.map +1 -1
- package/dist/log-hook.js +40 -31
- package/dist/log-hook.js.map +1 -1
- package/dist/plugin.d.ts +9 -7
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +229 -151
- package/dist/plugin.js.map +1 -1
- package/dist/rfc-8252-http-server.d.ts.map +1 -1
- package/dist/rfc-8252-http-server.js +165 -150
- package/dist/rfc-8252-http-server.js.map +1 -1
- package/dist/types.d.ts +29 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +5 -6
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +39 -4
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +85 -30
- package/dist/util.js.map +1 -1
- package/index.d.ts +41 -5
- package/package.json +18 -16
package/dist/plugin.js
CHANGED
|
@@ -15,25 +15,35 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.MongoDBOIDCPluginImpl =
|
|
36
|
+
exports.MongoDBOIDCPluginImpl = void 0;
|
|
37
|
+
exports.automaticRefreshTimeoutMS = automaticRefreshTimeoutMS;
|
|
27
38
|
const types_1 = require("./types");
|
|
28
39
|
const util_1 = require("./util");
|
|
29
|
-
const openid_client_1 = require("openid-client");
|
|
30
|
-
const openid_client_2 = require("openid-client");
|
|
31
40
|
const rfc_8252_http_server_1 = require("./rfc-8252-http-server");
|
|
32
|
-
const util_2 = require("util");
|
|
33
|
-
const crypto_1 = require("crypto");
|
|
34
41
|
const events_1 = require("events");
|
|
35
42
|
const api_1 = require("./api");
|
|
36
43
|
const child_process_1 = require("child_process");
|
|
44
|
+
const openid_client_1 = require("openid-client");
|
|
45
|
+
const https_1 = require("https");
|
|
46
|
+
const http_1 = require("http");
|
|
37
47
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
38
48
|
let _electron = undefined;
|
|
39
49
|
async function getDefaultOpenBrowser() {
|
|
@@ -41,7 +51,7 @@ async function getDefaultOpenBrowser() {
|
|
|
41
51
|
// to open a browser.
|
|
42
52
|
if (process.versions.electron && _electron !== 'cannot-require') {
|
|
43
53
|
try {
|
|
44
|
-
_electron
|
|
54
|
+
_electron ??= await Promise.resolve().then(() => __importStar(require('electron')));
|
|
45
55
|
return ({ url }) =>
|
|
46
56
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
47
57
|
_electron.shell.openExternal(url);
|
|
@@ -88,17 +98,17 @@ function tokenExpiryInSeconds(tokenSet = {}, passIdTokenAsAccessToken = false, n
|
|
|
88
98
|
// specifies the token expiry. Otherwise, we assume that the `expires_at`
|
|
89
99
|
// value presented by the OIDC provider is correct, since OIDC clients are
|
|
90
100
|
// not supposed to inspect access tokens and treat them as opaque.
|
|
91
|
-
const expiresAt = (tokenSet.
|
|
101
|
+
const expiresAt = (tokenSet.idTokenClaims?.exp !== undefined &&
|
|
92
102
|
passIdTokenAsAccessToken &&
|
|
93
|
-
tokenSet.
|
|
94
|
-
tokenSet.
|
|
103
|
+
tokenSet.idTokenClaims?.exp) ||
|
|
104
|
+
tokenSet.expiresAt ||
|
|
95
105
|
0;
|
|
96
106
|
return Math.max(0, (expiresAt ?? 0) - now / 1000);
|
|
97
107
|
}
|
|
98
108
|
/** @internal Exported for testing only */
|
|
99
109
|
function automaticRefreshTimeoutMS(tokenSet, passIdTokenAsAccessToken = false, now = Date.now()) {
|
|
100
110
|
const expiresIn = tokenExpiryInSeconds(tokenSet, passIdTokenAsAccessToken, now);
|
|
101
|
-
if (!tokenSet.
|
|
111
|
+
if (!tokenSet.refreshToken || !expiresIn)
|
|
102
112
|
return;
|
|
103
113
|
// If the tokens expire in more than 1 minute, automatically register
|
|
104
114
|
// a refresh handler. (They should not expire in less; however,
|
|
@@ -110,9 +120,9 @@ function automaticRefreshTimeoutMS(tokenSet, passIdTokenAsAccessToken = false, n
|
|
|
110
120
|
return Math.max(expiresIn - 300 /* 5 minutes */, expiresIn / 2) * 1000;
|
|
111
121
|
}
|
|
112
122
|
}
|
|
113
|
-
exports.automaticRefreshTimeoutMS = automaticRefreshTimeoutMS;
|
|
114
123
|
const kEnableFallback = Symbol.for('@@mdb.oidcplugin.kEnableFallback');
|
|
115
124
|
let updateIdCounter = 0;
|
|
125
|
+
let authStateIdCounter = 0;
|
|
116
126
|
function allowFallbackIfFailed(promise) {
|
|
117
127
|
return promise.catch((err) => {
|
|
118
128
|
// Tell the outer logic here to fallback to device auth flow if it is
|
|
@@ -125,9 +135,13 @@ function allowFallbackIfFailed(promise) {
|
|
|
125
135
|
}
|
|
126
136
|
/** @internal */
|
|
127
137
|
class MongoDBOIDCPluginImpl {
|
|
138
|
+
options;
|
|
139
|
+
logger;
|
|
140
|
+
mapIdpToAuthState = new Map();
|
|
141
|
+
mongoClientOptions;
|
|
142
|
+
timers;
|
|
143
|
+
destroyed = false;
|
|
128
144
|
constructor(options) {
|
|
129
|
-
this.mapIdpToAuthState = new Map();
|
|
130
|
-
this.destroyed = false;
|
|
131
145
|
this.options = options;
|
|
132
146
|
this.logger = options.logger ?? new events_1.EventEmitter();
|
|
133
147
|
this.mongoClientOptions = {
|
|
@@ -140,6 +154,12 @@ class MongoDBOIDCPluginImpl {
|
|
|
140
154
|
this._deserialize(options.serializedState);
|
|
141
155
|
}
|
|
142
156
|
}
|
|
157
|
+
/** @internal Public for testing only. */
|
|
158
|
+
static createOIDCAuthStateId() {
|
|
159
|
+
// Use an ID for the OIDC auth state, so that we can distinguish
|
|
160
|
+
// between different auth states in logs.
|
|
161
|
+
return `${Date.now().toString(32)}-${authStateIdCounter++}`;
|
|
162
|
+
}
|
|
143
163
|
_deserialize(serialized) {
|
|
144
164
|
try {
|
|
145
165
|
let original;
|
|
@@ -147,13 +167,14 @@ class MongoDBOIDCPluginImpl {
|
|
|
147
167
|
original = JSON.parse(Buffer.from(serialized, 'base64').toString('utf8'));
|
|
148
168
|
}
|
|
149
169
|
catch (err) {
|
|
150
|
-
throw new types_1.MongoDBOIDCError(`Stored OIDC data could not be deserialized: ${err.message}
|
|
170
|
+
throw new types_1.MongoDBOIDCError(`Stored OIDC data could not be deserialized: ${err.message}`, { cause: err, codeName: 'DeserializeFormatMismatch' });
|
|
151
171
|
}
|
|
152
|
-
if (original.oidcPluginStateVersion !==
|
|
153
|
-
throw new types_1.MongoDBOIDCError(`Stored OIDC data could not be deserialized because of a version mismatch (got ${JSON.stringify(original.oidcPluginStateVersion)}, expected
|
|
172
|
+
if (original.oidcPluginStateVersion !== 1) {
|
|
173
|
+
throw new types_1.MongoDBOIDCError(`Stored OIDC data could not be deserialized because of a version mismatch (got ${JSON.stringify(original.oidcPluginStateVersion)}, expected 1)`, { codeName: 'DeserializeVersionMismatch' });
|
|
154
174
|
}
|
|
155
175
|
for (const [key, serializedState] of original.state) {
|
|
156
176
|
const state = {
|
|
177
|
+
id: serializedState.id ?? MongoDBOIDCPluginImpl.createOIDCAuthStateId(),
|
|
157
178
|
serverOIDCMetadata: { ...serializedState.serverOIDCMetadata },
|
|
158
179
|
currentAuthAttempt: null,
|
|
159
180
|
currentTokenSet: null,
|
|
@@ -162,7 +183,9 @@ class MongoDBOIDCPluginImpl {
|
|
|
162
183
|
: undefined,
|
|
163
184
|
discardingTokenSets: serializedState.discardingTokenSets,
|
|
164
185
|
};
|
|
165
|
-
|
|
186
|
+
if (serializedState.currentTokenSet.set) {
|
|
187
|
+
this.updateStateWithTokenSet(state, util_1.TokenSet.fromSerialized(serializedState.currentTokenSet.set));
|
|
188
|
+
}
|
|
166
189
|
this.mapIdpToAuthState.set(key, state);
|
|
167
190
|
}
|
|
168
191
|
}
|
|
@@ -180,16 +203,17 @@ class MongoDBOIDCPluginImpl {
|
|
|
180
203
|
// Separate method so we can re-use the inferred return type in _deserialize()
|
|
181
204
|
_serialize() {
|
|
182
205
|
return {
|
|
183
|
-
oidcPluginStateVersion:
|
|
206
|
+
oidcPluginStateVersion: 1,
|
|
184
207
|
state: [...this.mapIdpToAuthState]
|
|
185
208
|
.filter(([, state]) => !!state.currentTokenSet)
|
|
186
209
|
.map(([key, state]) => {
|
|
187
210
|
return [
|
|
188
211
|
key,
|
|
189
212
|
{
|
|
213
|
+
id: state.id,
|
|
190
214
|
serverOIDCMetadata: { ...state.serverOIDCMetadata },
|
|
191
215
|
currentTokenSet: {
|
|
192
|
-
set:
|
|
216
|
+
set: state.currentTokenSet?.set?.serialize(),
|
|
193
217
|
},
|
|
194
218
|
lastIdTokenClaims: state.lastIdTokenClaims
|
|
195
219
|
? { ...state.lastIdTokenClaims }
|
|
@@ -222,11 +246,13 @@ class MongoDBOIDCPluginImpl {
|
|
|
222
246
|
// or create a new one if none exists.
|
|
223
247
|
getAuthState(serverMetadata) {
|
|
224
248
|
if (!serverMetadata.issuer || typeof serverMetadata.issuer !== 'string') {
|
|
225
|
-
throw new types_1.MongoDBOIDCError(`'issuer' is missing
|
|
249
|
+
throw new types_1.MongoDBOIDCError(`'issuer' is missing`, {
|
|
250
|
+
codeName: 'MissingIssuer',
|
|
251
|
+
});
|
|
226
252
|
}
|
|
227
253
|
(0, util_1.validateSecureHTTPUrl)(serverMetadata.issuer, 'issuer');
|
|
228
254
|
if (!serverMetadata.clientId) {
|
|
229
|
-
throw new types_1.MongoDBOIDCError('No clientId passed in server OIDC metadata object');
|
|
255
|
+
throw new types_1.MongoDBOIDCError('No clientId passed in server OIDC metadata object', { codeName: 'MissingClientId' });
|
|
230
256
|
}
|
|
231
257
|
const key = JSON.stringify({
|
|
232
258
|
// If any part of the server metadata changes, we should probably use
|
|
@@ -238,101 +264,109 @@ class MongoDBOIDCPluginImpl {
|
|
|
238
264
|
return existing;
|
|
239
265
|
const newState = {
|
|
240
266
|
serverOIDCMetadata: serverMetadata,
|
|
267
|
+
id: MongoDBOIDCPluginImpl.createOIDCAuthStateId(),
|
|
241
268
|
currentAuthAttempt: null,
|
|
242
269
|
currentTokenSet: null,
|
|
243
270
|
};
|
|
244
271
|
this.mapIdpToAuthState.set(key, newState);
|
|
245
272
|
return newState;
|
|
246
273
|
}
|
|
247
|
-
getSupportedDefaultScopes(
|
|
274
|
+
getSupportedDefaultScopes(idpMetadata) {
|
|
248
275
|
return ['openid', 'offline_access'].filter((scope) => {
|
|
249
276
|
// Only add `openid` / `offline_access` if the IdP announces support
|
|
250
277
|
// for those scopes, or if the IdP does not provide a list of scopes
|
|
251
278
|
// and we cannot tell which it supports.
|
|
252
279
|
// https://jira.mongodb.org/browser/COMPASS-7437
|
|
253
|
-
return (!Array.isArray(
|
|
254
|
-
|
|
280
|
+
return (!Array.isArray(idpMetadata.scopes_supported) ||
|
|
281
|
+
idpMetadata.scopes_supported.includes(scope));
|
|
255
282
|
});
|
|
256
283
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
static async discover(issuer) {
|
|
279
|
-
return new this((await super.discover(issuer)).metadata);
|
|
284
|
+
fetch = async (url, init) => {
|
|
285
|
+
this.logger.emit('mongodb-oidc-plugin:outbound-http-request', { url });
|
|
286
|
+
if (this.options.customFetch) {
|
|
287
|
+
return await this.options.customFetch(url, init);
|
|
288
|
+
}
|
|
289
|
+
const options = typeof this.options.customHttpOptions === 'function'
|
|
290
|
+
? this.options.customHttpOptions(url, {})
|
|
291
|
+
: this.options.customHttpOptions;
|
|
292
|
+
// Same comments as in getDefaultOpenBrowser() apply regarding the import/eval fallbacks here.
|
|
293
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
294
|
+
let fetch;
|
|
295
|
+
try {
|
|
296
|
+
fetch = (await Promise.resolve().then(() => __importStar(require('node-fetch')))).default;
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
if (err &&
|
|
300
|
+
typeof err === 'object' &&
|
|
301
|
+
'code' in err &&
|
|
302
|
+
err.code === 'ERR_REQUIRE_ESM' &&
|
|
303
|
+
typeof __webpack_require__ === 'undefined') {
|
|
304
|
+
fetch = (await eval('import("node-fetch")')).default;
|
|
280
305
|
}
|
|
281
|
-
|
|
282
|
-
|
|
306
|
+
else {
|
|
307
|
+
throw err;
|
|
283
308
|
}
|
|
284
309
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
310
|
+
const AgentClass = new URL(url).protocol === 'https:' ? https_1.Agent : http_1.Agent;
|
|
311
|
+
return (await fetch(url, {
|
|
312
|
+
...init,
|
|
313
|
+
agent: options?.agent ?? new AgentClass(options),
|
|
314
|
+
...options,
|
|
315
|
+
headers: { ...options?.headers },
|
|
316
|
+
// TS is not convinced that node-fetch and built-in fetch are compatible enough
|
|
317
|
+
}));
|
|
318
|
+
};
|
|
319
|
+
async getOIDCClientConfiguration(state, redirectURI) {
|
|
290
320
|
const serverMetadata = state.serverOIDCMetadata;
|
|
291
|
-
const makeScope = (
|
|
321
|
+
const makeScope = (idpMetadata) => [
|
|
292
322
|
...new Set([
|
|
293
|
-
...this.getSupportedDefaultScopes(
|
|
323
|
+
...this.getSupportedDefaultScopes(idpMetadata),
|
|
294
324
|
...(serverMetadata.requestScopes ?? []),
|
|
295
325
|
]),
|
|
296
326
|
].join(' ');
|
|
297
|
-
if (state.
|
|
327
|
+
if (state.config) {
|
|
328
|
+
const config = new openid_client_1.Configuration(state.config.serverMetadata(), state.config.clientMetadata().client_id, {
|
|
329
|
+
...state.config.clientMetadata(),
|
|
330
|
+
redirect_uri: redirectURI,
|
|
331
|
+
});
|
|
332
|
+
if ((0, util_1.validateSecureHTTPUrl)(config.serverMetadata().issuer, 'issuer') ===
|
|
333
|
+
'http-allowed') {
|
|
334
|
+
(0, openid_client_1.allowInsecureRequests)(config);
|
|
335
|
+
}
|
|
298
336
|
return {
|
|
299
|
-
scope: makeScope(
|
|
300
|
-
|
|
301
|
-
// need to re-create Client here because redirect_uris might
|
|
302
|
-
// differ between calls to this method
|
|
303
|
-
client: new state.client.issuer.Client({
|
|
304
|
-
...state.client.metadata,
|
|
305
|
-
redirect_uris: redirectURIs,
|
|
306
|
-
}),
|
|
337
|
+
scope: makeScope(config.serverMetadata()),
|
|
338
|
+
config,
|
|
307
339
|
};
|
|
308
340
|
}
|
|
309
|
-
(0, util_1.validateSecureHTTPUrl)(serverMetadata.issuer, 'issuer');
|
|
310
|
-
|
|
341
|
+
const httpAllowed = (0, util_1.validateSecureHTTPUrl)(serverMetadata.issuer, 'issuer');
|
|
342
|
+
const discoveryOptions = {
|
|
343
|
+
[openid_client_1.customFetch]: this.fetch,
|
|
344
|
+
execute: httpAllowed === 'http-allowed' ? [openid_client_1.allowInsecureRequests] : [],
|
|
345
|
+
};
|
|
346
|
+
let config;
|
|
311
347
|
try {
|
|
312
|
-
|
|
348
|
+
config = await (0, openid_client_1.discovery)(new URL(serverMetadata.issuer), serverMetadata.clientId, {
|
|
349
|
+
redirect_uri: redirectURI,
|
|
350
|
+
}, (0, openid_client_1.None)(), discoveryOptions);
|
|
351
|
+
// NB: The fact that `customFetch` is transfered from `discoveryOptions` to `config`
|
|
352
|
+
// is tested by our unit tests when they verify that all outgoing HTTP calls are logged.
|
|
313
353
|
}
|
|
314
354
|
catch (err) {
|
|
315
355
|
// openid-client just forwards the raw Node.js HTTP error, we'll want to
|
|
316
356
|
// at least include the target URL here
|
|
317
357
|
throw new types_1.MongoDBOIDCError(`Unable to fetch issuer metadata for ${JSON.stringify(serverMetadata.issuer)}: ${(0, util_1.messageFromError)(err)}`, {
|
|
318
358
|
cause: err,
|
|
359
|
+
codeName: 'IssuerMetadataDiscoveryFailed',
|
|
319
360
|
});
|
|
320
361
|
}
|
|
321
|
-
(0, util_1.validateSecureHTTPUrl)(
|
|
322
|
-
(0, util_1.validateSecureHTTPUrl)(
|
|
323
|
-
(0, util_1.validateSecureHTTPUrl)(
|
|
324
|
-
(0, util_1.validateSecureHTTPUrl)(
|
|
325
|
-
|
|
326
|
-
client_id: serverMetadata.clientId,
|
|
327
|
-
redirect_uris: redirectURIs,
|
|
328
|
-
response_types: ['code'],
|
|
329
|
-
token_endpoint_auth_method: 'none',
|
|
330
|
-
});
|
|
331
|
-
state.client = client;
|
|
362
|
+
(0, util_1.validateSecureHTTPUrl)(config.serverMetadata().authorization_endpoint, 'authorization_endpoint');
|
|
363
|
+
(0, util_1.validateSecureHTTPUrl)(config.serverMetadata().device_authorization_endpoint, 'device_authorization_endpoint');
|
|
364
|
+
(0, util_1.validateSecureHTTPUrl)(config.serverMetadata().token_endpoint, 'token_endpoint');
|
|
365
|
+
(0, util_1.validateSecureHTTPUrl)(config.serverMetadata().jwks_uri, 'jwks_uri');
|
|
366
|
+
state.config = config;
|
|
332
367
|
return {
|
|
333
|
-
scope: makeScope(
|
|
334
|
-
|
|
335
|
-
client,
|
|
368
|
+
scope: makeScope(config.serverMetadata()),
|
|
369
|
+
config,
|
|
336
370
|
};
|
|
337
371
|
}
|
|
338
372
|
async openBrowser(options) {
|
|
@@ -344,14 +378,14 @@ class MongoDBOIDCPluginImpl {
|
|
|
344
378
|
// URL has this format.
|
|
345
379
|
new URL(options.url);
|
|
346
380
|
if (!/^[a-zA-Z0-9%/:;_.,=@-]+$/.test(options.url)) {
|
|
347
|
-
throw new types_1.MongoDBOIDCError(`Unexpected format for internally generated URL: '${options.url}'
|
|
381
|
+
throw new types_1.MongoDBOIDCError(`Unexpected format for internally generated URL: '${options.url}'`, { codeName: 'GeneratedUrlInvalidForOpenBrowserCommand' });
|
|
348
382
|
}
|
|
349
383
|
this.logger.emit('mongodb-oidc-plugin:open-browser', {
|
|
350
384
|
customOpener: !!this.options.openBrowser,
|
|
351
385
|
});
|
|
352
386
|
if (this.options.openBrowser === false) {
|
|
353
387
|
// We should never really get to this point
|
|
354
|
-
throw new types_1.MongoDBOIDCError('Cannot open browser if `openBrowser` is false');
|
|
388
|
+
throw new types_1.MongoDBOIDCError('Cannot open browser if `openBrowser` is false', { codeName: 'OpenBrowserDisabled' });
|
|
355
389
|
}
|
|
356
390
|
if (typeof this.options.openBrowser === 'function') {
|
|
357
391
|
return await this.options.openBrowser(options);
|
|
@@ -370,13 +404,15 @@ class MongoDBOIDCPluginImpl {
|
|
|
370
404
|
child.unref();
|
|
371
405
|
return child;
|
|
372
406
|
}
|
|
373
|
-
throw new types_1.MongoDBOIDCError('Unknown format for `openBrowser`'
|
|
407
|
+
throw new types_1.MongoDBOIDCError('Unknown format for `openBrowser`', {
|
|
408
|
+
codeName: 'OpenBrowserOptionFormatUnknown',
|
|
409
|
+
});
|
|
374
410
|
}
|
|
375
411
|
async notifyDeviceFlow(deviceFlowInformation) {
|
|
376
412
|
(0, util_1.validateSecureHTTPUrl)(deviceFlowInformation.verificationUrl, 'verificationUrl');
|
|
377
413
|
if (!this.options.notifyDeviceFlow) {
|
|
378
414
|
// Should never happen.
|
|
379
|
-
throw new types_1.MongoDBOIDCError('notifyDeviceFlow() requested but not provided');
|
|
415
|
+
throw new types_1.MongoDBOIDCError('notifyDeviceFlow() requested but not provided', { codeName: 'DeviceFlowNotEnabled' });
|
|
380
416
|
}
|
|
381
417
|
this.logger.emit('mongodb-oidc-plugin:notify-device-flow');
|
|
382
418
|
await this.options.notifyDeviceFlow(deviceFlowInformation);
|
|
@@ -388,18 +424,22 @@ class MongoDBOIDCPluginImpl {
|
|
|
388
424
|
// for client A, the token expires before it is requested again by client A,
|
|
389
425
|
// then the plugin is passed to client B which requests a token, and we
|
|
390
426
|
// receive mismatching tokens for different users or different audiences.
|
|
391
|
-
if (!tokenSet.
|
|
427
|
+
if (!tokenSet.idToken &&
|
|
392
428
|
state.lastIdTokenClaims &&
|
|
393
429
|
!state.lastIdTokenClaims.noIdToken) {
|
|
394
|
-
throw new types_1.MongoDBOIDCError(`ID token expected, but not found. Expected claims: ${JSON.stringify(state.lastIdTokenClaims)}
|
|
430
|
+
throw new types_1.MongoDBOIDCError(`ID token expected, but not found. Expected claims: ${JSON.stringify(state.lastIdTokenClaims)}`, { codeName: 'IDTokenClaimsMismatchTokenMissing' });
|
|
395
431
|
}
|
|
396
|
-
if (tokenSet.
|
|
432
|
+
if (tokenSet.idToken &&
|
|
397
433
|
state.lastIdTokenClaims &&
|
|
398
434
|
state.lastIdTokenClaims.noIdToken) {
|
|
399
|
-
throw new types_1.MongoDBOIDCError(`Unexpected ID token received
|
|
435
|
+
throw new types_1.MongoDBOIDCError(`Unexpected ID token received.`, {
|
|
436
|
+
codeName: 'IDTokenClaimsMismatchTokenUnexpectedlyPresent',
|
|
437
|
+
});
|
|
400
438
|
}
|
|
401
|
-
if (tokenSet.
|
|
402
|
-
const idTokenClaims = tokenSet.
|
|
439
|
+
if (tokenSet.idToken) {
|
|
440
|
+
const idTokenClaims = tokenSet.idTokenClaims;
|
|
441
|
+
if (!idTokenClaims)
|
|
442
|
+
throw new types_1.MongoDBOIDCError('Internal error: id_token set but claims() unavailable', { codeName: 'IDTokenClaimsUnavailable' });
|
|
403
443
|
if (state.lastIdTokenClaims && !state.lastIdTokenClaims.noIdToken) {
|
|
404
444
|
for (const claim of ['aud', 'sub']) {
|
|
405
445
|
const normalize = (value) => {
|
|
@@ -408,7 +448,7 @@ class MongoDBOIDCPluginImpl {
|
|
|
408
448
|
const knownClaim = normalize(state.lastIdTokenClaims[claim]);
|
|
409
449
|
const newClaim = normalize(idTokenClaims[claim]);
|
|
410
450
|
if (knownClaim !== newClaim) {
|
|
411
|
-
throw new types_1.MongoDBOIDCError(`Unexpected '${claim}' field in id token: Expected ${knownClaim}, saw ${newClaim}
|
|
451
|
+
throw new types_1.MongoDBOIDCError(`Unexpected '${claim}' field in id token: Expected ${knownClaim}, saw ${newClaim}`, { codeName: 'IDTokenClaimsMismatchClaimMismatch' });
|
|
412
452
|
}
|
|
413
453
|
}
|
|
414
454
|
}
|
|
@@ -421,7 +461,7 @@ class MongoDBOIDCPluginImpl {
|
|
|
421
461
|
state.lastIdTokenClaims = { noIdToken: true };
|
|
422
462
|
this.logger.emit('mongodb-oidc-plugin:missing-id-token');
|
|
423
463
|
}
|
|
424
|
-
const refreshTokenId = (0, util_1.getRefreshTokenId)(tokenSet.
|
|
464
|
+
const refreshTokenId = (0, util_1.getRefreshTokenId)(tokenSet.refreshToken);
|
|
425
465
|
const updateId = updateIdCounter++;
|
|
426
466
|
const timerDuration = automaticRefreshTimeoutMS(tokenSet, this.options.passIdTokenAsAccessToken);
|
|
427
467
|
// Use `.call()` because in browsers, `setTimeout()` requires that it is called
|
|
@@ -443,7 +483,7 @@ class MongoDBOIDCPluginImpl {
|
|
|
443
483
|
this.logger.emit('mongodb-oidc-plugin:refresh-skipped', {
|
|
444
484
|
triggeringUpdateId: updateId,
|
|
445
485
|
expectedRefreshToken: refreshTokenId,
|
|
446
|
-
actualRefreshToken: (0, util_1.getRefreshTokenId)(state.currentTokenSet?.set?.
|
|
486
|
+
actualRefreshToken: (0, util_1.getRefreshTokenId)(state.currentTokenSet?.set?.refreshToken),
|
|
447
487
|
});
|
|
448
488
|
return false;
|
|
449
489
|
}
|
|
@@ -452,15 +492,17 @@ class MongoDBOIDCPluginImpl {
|
|
|
452
492
|
triggeringUpdateId: updateId,
|
|
453
493
|
refreshToken: refreshTokenId,
|
|
454
494
|
});
|
|
455
|
-
|
|
456
|
-
|
|
495
|
+
if (!tokenSet.refreshToken)
|
|
496
|
+
return false;
|
|
497
|
+
const { config } = await this.getOIDCClientConfiguration(state);
|
|
498
|
+
const refreshedTokens = await (0, openid_client_1.refreshTokenGrant)(config, tokenSet.refreshToken);
|
|
457
499
|
// Check again to avoid race conditions.
|
|
458
500
|
if (state.currentTokenSet?.set === tokenSet) {
|
|
459
501
|
this.logger.emit('mongodb-oidc-plugin:refresh-succeeded', {
|
|
460
502
|
triggeringUpdateId: updateId,
|
|
461
503
|
refreshToken: refreshTokenId,
|
|
462
504
|
});
|
|
463
|
-
this.updateStateWithTokenSet(state, refreshedTokens);
|
|
505
|
+
this.updateStateWithTokenSet(state, new util_1.TokenSet(refreshedTokens));
|
|
464
506
|
return true;
|
|
465
507
|
}
|
|
466
508
|
}
|
|
@@ -480,14 +522,15 @@ class MongoDBOIDCPluginImpl {
|
|
|
480
522
|
this.logger.emit('mongodb-oidc-plugin:state-updated', {
|
|
481
523
|
updateId,
|
|
482
524
|
timerDuration,
|
|
483
|
-
tokenSetId:
|
|
525
|
+
tokenSetId: tokenSet.stableId(),
|
|
484
526
|
});
|
|
485
527
|
}
|
|
528
|
+
static defaultRedirectURI = 'http://localhost:27097/redirect';
|
|
486
529
|
async authorizationCodeFlow(state, signal) {
|
|
487
530
|
const configuredRedirectURI = this.options.redirectURI ?? MongoDBOIDCPluginImpl.defaultRedirectURI;
|
|
488
|
-
const codeVerifier =
|
|
489
|
-
const codeChallenge =
|
|
490
|
-
const oidcStateParam = (
|
|
531
|
+
const codeVerifier = (0, openid_client_1.randomPKCECodeVerifier)();
|
|
532
|
+
const codeChallenge = await (0, openid_client_1.calculatePKCECodeChallenge)(codeVerifier);
|
|
533
|
+
const oidcStateParam = (0, openid_client_1.randomState)();
|
|
491
534
|
const server = new rfc_8252_http_server_1.RFC8252HTTPServer({
|
|
492
535
|
redirectUrl: configuredRedirectURI,
|
|
493
536
|
logger: this.logger,
|
|
@@ -496,11 +539,11 @@ class MongoDBOIDCPluginImpl {
|
|
|
496
539
|
});
|
|
497
540
|
let paramsUrl = '';
|
|
498
541
|
let scope;
|
|
499
|
-
let
|
|
542
|
+
let config;
|
|
500
543
|
let actualRedirectURI;
|
|
501
544
|
const nonce = this.options.skipNonceInAuthCodeRequest
|
|
502
545
|
? undefined
|
|
503
|
-
:
|
|
546
|
+
: (0, openid_client_1.randomNonce)();
|
|
504
547
|
try {
|
|
505
548
|
await (0, util_1.withAbortCheck)(signal, async ({ signalCheck, signalPromise }) => {
|
|
506
549
|
// We mark the operations that we want to allow to result in a fallback
|
|
@@ -514,18 +557,17 @@ class MongoDBOIDCPluginImpl {
|
|
|
514
557
|
signalPromise,
|
|
515
558
|
]);
|
|
516
559
|
actualRedirectURI = server.listeningRedirectUrl;
|
|
517
|
-
({ scope,
|
|
518
|
-
|
|
519
|
-
]));
|
|
520
|
-
const authCodeFlowUrl = client.authorizationUrl({
|
|
560
|
+
({ scope, config } = await this.getOIDCClientConfiguration(state, actualRedirectURI));
|
|
561
|
+
const authCodeFlowUrl = (0, openid_client_1.buildAuthorizationUrl)(config, {
|
|
521
562
|
scope,
|
|
522
563
|
code_challenge: codeChallenge,
|
|
523
564
|
code_challenge_method: 'S256',
|
|
524
565
|
state: oidcStateParam,
|
|
525
|
-
nonce,
|
|
566
|
+
...(nonce ? { nonce } : {}),
|
|
567
|
+
redirect_uri: actualRedirectURI,
|
|
526
568
|
});
|
|
527
569
|
(0, util_1.validateSecureHTTPUrl)(authCodeFlowUrl, 'authCodeFlowUrl');
|
|
528
|
-
const { localUrl, onAccessed: onLocalUrlAccessed } = await server.addRedirect(authCodeFlowUrl);
|
|
570
|
+
const { localUrl, onAccessed: onLocalUrlAccessed } = await server.addRedirect(authCodeFlowUrl.toString());
|
|
529
571
|
signalCheck();
|
|
530
572
|
// Handle errors from opening a browser but do not await the Promise
|
|
531
573
|
// in case it only resolves when the browser exits (which is the case
|
|
@@ -537,10 +579,10 @@ class MongoDBOIDCPluginImpl {
|
|
|
537
579
|
const extraErrorInfo = () => browserHandle?.spawnargs
|
|
538
580
|
? ` (${JSON.stringify(browserHandle.spawnargs)})`
|
|
539
581
|
: '';
|
|
540
|
-
browserHandle?.once('error', (err) => reject(new types_1.MongoDBOIDCError(`Opening browser failed with '${(0, util_1.messageFromError)(err)}'${extraErrorInfo()}`, { cause: err })));
|
|
582
|
+
browserHandle?.once('error', (err) => reject(new types_1.MongoDBOIDCError(`Opening browser failed with '${(0, util_1.messageFromError)(err)}'${extraErrorInfo()}`, { cause: err, codeName: 'BrowserOpenFailedSpawnError' })));
|
|
541
583
|
browserHandle?.once('exit', (code) => {
|
|
542
584
|
if (code !== 0)
|
|
543
|
-
reject(new types_1.MongoDBOIDCError(`Opening browser failed with exit code ${code}${extraErrorInfo()}
|
|
585
|
+
reject(new types_1.MongoDBOIDCError(`Opening browser failed with exit code ${code}${extraErrorInfo()}`, { codeName: 'BrowserOpenFailedNonZeroExit' }));
|
|
544
586
|
});
|
|
545
587
|
})
|
|
546
588
|
.catch(reject);
|
|
@@ -548,7 +590,9 @@ class MongoDBOIDCPluginImpl {
|
|
|
548
590
|
const timeout = allowFallbackIfFailed(new Promise((resolve, reject) => {
|
|
549
591
|
if (this.options.openBrowserTimeout !== 0) {
|
|
550
592
|
this.timers.setTimeout
|
|
551
|
-
.call(null, () => reject(new types_1.MongoDBOIDCError('Opening browser timed out'
|
|
593
|
+
.call(null, () => reject(new types_1.MongoDBOIDCError('Opening browser timed out', {
|
|
594
|
+
codeName: 'BrowserOpenTimeout',
|
|
595
|
+
})), this.options.openBrowserTimeout ?? api_1.kDefaultOpenBrowserTimeout)
|
|
552
596
|
?.unref?.();
|
|
553
597
|
}
|
|
554
598
|
}));
|
|
@@ -570,20 +614,18 @@ class MongoDBOIDCPluginImpl {
|
|
|
570
614
|
finally {
|
|
571
615
|
await server.close();
|
|
572
616
|
}
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
nonce,
|
|
617
|
+
const tokenSet = await (0, openid_client_1.authorizationCodeGrant)(config, new URL(paramsUrl), {
|
|
618
|
+
pkceCodeVerifier: codeVerifier,
|
|
619
|
+
expectedState: oidcStateParam,
|
|
620
|
+
expectedNonce: nonce,
|
|
578
621
|
});
|
|
579
|
-
this.updateStateWithTokenSet(state, tokenSet);
|
|
622
|
+
this.updateStateWithTokenSet(state, new util_1.TokenSet(tokenSet));
|
|
580
623
|
}
|
|
581
624
|
async deviceAuthorizationFlow(state, signal) {
|
|
582
|
-
const { scope,
|
|
625
|
+
const { scope, config } = await this.getOIDCClientConfiguration(state);
|
|
583
626
|
await (0, util_1.withAbortCheck)(signal, async ({ signalCheck, signalPromise }) => {
|
|
584
627
|
const deviceFlowHandle = await Promise.race([
|
|
585
|
-
|
|
586
|
-
client_id: client.metadata.client_id,
|
|
628
|
+
(0, openid_client_1.initiateDeviceAuthorization)(config, {
|
|
587
629
|
scope,
|
|
588
630
|
}),
|
|
589
631
|
signalPromise,
|
|
@@ -593,8 +635,8 @@ class MongoDBOIDCPluginImpl {
|
|
|
593
635
|
userCode: deviceFlowHandle.user_code,
|
|
594
636
|
verificationUrl: deviceFlowHandle.verification_uri,
|
|
595
637
|
});
|
|
596
|
-
const tokenSet = await
|
|
597
|
-
this.updateStateWithTokenSet(state, tokenSet);
|
|
638
|
+
const tokenSet = await (0, openid_client_1.pollDeviceAuthorizationGrant)(config, deviceFlowHandle, {}, { signal });
|
|
639
|
+
this.updateStateWithTokenSet(state, new util_1.TokenSet(tokenSet));
|
|
598
640
|
});
|
|
599
641
|
}
|
|
600
642
|
async initiateAuthAttempt(state, driverAbortSignal, { forceRefreshOrReauth = false } = {}) {
|
|
@@ -619,12 +661,14 @@ class MongoDBOIDCPluginImpl {
|
|
|
619
661
|
tokenExpiryInSeconds(state.currentTokenSet?.set, passIdTokenAsAccessToken) >
|
|
620
662
|
5 * 60) {
|
|
621
663
|
this.logger.emit('mongodb-oidc-plugin:skip-auth-attempt', {
|
|
664
|
+
authStateId: state.id,
|
|
622
665
|
reason: 'not-expired',
|
|
623
666
|
});
|
|
624
667
|
break get_tokens;
|
|
625
668
|
}
|
|
626
669
|
if (await state.currentTokenSet?.tryRefresh?.()) {
|
|
627
670
|
this.logger.emit('mongodb-oidc-plugin:skip-auth-attempt', {
|
|
671
|
+
authStateId: state.id,
|
|
628
672
|
reason: 'refresh-succeeded',
|
|
629
673
|
});
|
|
630
674
|
break get_tokens;
|
|
@@ -635,15 +679,19 @@ class MongoDBOIDCPluginImpl {
|
|
|
635
679
|
if (currentAllowedFlowSet.includes('auth-code')) {
|
|
636
680
|
try {
|
|
637
681
|
this.logger.emit('mongodb-oidc-plugin:auth-attempt-started', {
|
|
682
|
+
authStateId: state.id,
|
|
638
683
|
flow: 'auth-code',
|
|
639
684
|
});
|
|
640
685
|
await this.authorizationCodeFlow(state, signal);
|
|
641
|
-
this.logger.emit('mongodb-oidc-plugin:auth-attempt-succeeded'
|
|
686
|
+
this.logger.emit('mongodb-oidc-plugin:auth-attempt-succeeded', {
|
|
687
|
+
authStateId: state.id,
|
|
688
|
+
});
|
|
642
689
|
break get_tokens;
|
|
643
690
|
}
|
|
644
691
|
catch (err) {
|
|
645
692
|
error = err;
|
|
646
693
|
this.logger.emit('mongodb-oidc-plugin:auth-attempt-failed', {
|
|
694
|
+
authStateId: state.id,
|
|
647
695
|
error: (0, util_1.errorString)(err),
|
|
648
696
|
});
|
|
649
697
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -654,14 +702,18 @@ class MongoDBOIDCPluginImpl {
|
|
|
654
702
|
if (currentAllowedFlowSet.includes('device-auth')) {
|
|
655
703
|
try {
|
|
656
704
|
this.logger.emit('mongodb-oidc-plugin:auth-attempt-started', {
|
|
705
|
+
authStateId: state.id,
|
|
657
706
|
flow: 'device-auth',
|
|
658
707
|
});
|
|
659
708
|
await this.deviceAuthorizationFlow(state, signal);
|
|
660
|
-
this.logger.emit('mongodb-oidc-plugin:auth-attempt-succeeded'
|
|
709
|
+
this.logger.emit('mongodb-oidc-plugin:auth-attempt-succeeded', {
|
|
710
|
+
authStateId: state.id,
|
|
711
|
+
});
|
|
661
712
|
break get_tokens;
|
|
662
713
|
}
|
|
663
714
|
catch (err) {
|
|
664
715
|
this.logger.emit('mongodb-oidc-plugin:auth-attempt-failed', {
|
|
716
|
+
authStateId: state.id,
|
|
665
717
|
error: (0, util_1.errorString)(err),
|
|
666
718
|
});
|
|
667
719
|
throw err;
|
|
@@ -670,15 +722,20 @@ class MongoDBOIDCPluginImpl {
|
|
|
670
722
|
if (error)
|
|
671
723
|
throw error;
|
|
672
724
|
}
|
|
673
|
-
if (passIdTokenAsAccessToken && !state.currentTokenSet?.set?.
|
|
674
|
-
throw new types_1.MongoDBOIDCError('Could not retrieve valid ID token'
|
|
725
|
+
if (passIdTokenAsAccessToken && !state.currentTokenSet?.set?.idToken) {
|
|
726
|
+
throw new types_1.MongoDBOIDCError('Could not retrieve valid ID token', {
|
|
727
|
+
codeName: 'IDTokenMissingFromTokenSet',
|
|
728
|
+
});
|
|
675
729
|
}
|
|
676
|
-
else if (!state.currentTokenSet?.set?.
|
|
677
|
-
throw new types_1.MongoDBOIDCError('Could not retrieve valid access token'
|
|
730
|
+
else if (!state.currentTokenSet?.set?.accessToken) {
|
|
731
|
+
throw new types_1.MongoDBOIDCError('Could not retrieve valid access token', {
|
|
732
|
+
codeName: 'AccessTokenMissingFromTokenSet',
|
|
733
|
+
});
|
|
678
734
|
}
|
|
679
735
|
}
|
|
680
736
|
catch (err) {
|
|
681
737
|
this.logger.emit('mongodb-oidc-plugin:auth-failed', {
|
|
738
|
+
authStateId: state.id,
|
|
682
739
|
error: (0, util_1.errorString)(err),
|
|
683
740
|
});
|
|
684
741
|
throw err;
|
|
@@ -687,21 +744,23 @@ class MongoDBOIDCPluginImpl {
|
|
|
687
744
|
this.options.signal?.removeEventListener('abort', optionsAbortCb);
|
|
688
745
|
driverAbortSignal?.removeEventListener('abort', driverAbortCb);
|
|
689
746
|
}
|
|
690
|
-
const {
|
|
691
|
-
const
|
|
747
|
+
const { tokenType, accessToken, idToken, refreshToken } = state.currentTokenSet.set;
|
|
748
|
+
const expiresAt = state.currentTokenSet.set.expiresAt;
|
|
749
|
+
const tokenSetId = state.currentTokenSet.set.stableId();
|
|
692
750
|
// We would not want to return the access token or ID token of a token set whose
|
|
693
751
|
// accompanying refresh token was passed to us by the driver
|
|
694
752
|
const willRetryWithForceRefreshOrReauth = !forceRefreshOrReauth &&
|
|
695
753
|
!!state.discardingTokenSets?.includes(tokenSetId);
|
|
696
754
|
this.logger.emit('mongodb-oidc-plugin:auth-succeeded', {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
755
|
+
authStateId: state.id,
|
|
756
|
+
tokenType: tokenType ?? null, // DPoP or Bearer
|
|
757
|
+
refreshToken: (0, util_1.getRefreshTokenId)(refreshToken),
|
|
758
|
+
expiresAt: expiresAt ? new Date(expiresAt * 1000).toISOString() : null,
|
|
700
759
|
passIdTokenAsAccessToken: !!passIdTokenAsAccessToken,
|
|
701
760
|
tokens: {
|
|
702
|
-
accessToken:
|
|
703
|
-
idToken:
|
|
704
|
-
refreshToken:
|
|
761
|
+
accessToken: accessToken,
|
|
762
|
+
idToken: idToken,
|
|
763
|
+
refreshToken: refreshToken,
|
|
705
764
|
},
|
|
706
765
|
tokenSetId,
|
|
707
766
|
forceRefreshOrReauth,
|
|
@@ -713,7 +772,7 @@ class MongoDBOIDCPluginImpl {
|
|
|
713
772
|
});
|
|
714
773
|
}
|
|
715
774
|
return {
|
|
716
|
-
accessToken: passIdTokenAsAccessToken ?
|
|
775
|
+
accessToken: passIdTokenAsAccessToken ? idToken || '' : accessToken,
|
|
717
776
|
refreshToken: tokenSetId,
|
|
718
777
|
// Passing `expiresInSeconds: 0` results in the driver not caching the token.
|
|
719
778
|
// We perform our own caching here inside the plugin, so interactions with the
|
|
@@ -731,22 +790,33 @@ class MongoDBOIDCPluginImpl {
|
|
|
731
790
|
if (params.version !== 1) {
|
|
732
791
|
throw new types_1.MongoDBOIDCError(
|
|
733
792
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
734
|
-
`OIDC MongoDB driver protocol mismatch: unknown version ${params.version}
|
|
793
|
+
`OIDC MongoDB driver protocol mismatch: unknown version ${params.version}`, { codeName: 'ProtocolVersionMismatch' });
|
|
735
794
|
}
|
|
736
795
|
if (this.destroyed) {
|
|
737
|
-
throw new types_1.MongoDBOIDCError('This OIDC plugin instance has been destroyed and is no longer active');
|
|
796
|
+
throw new types_1.MongoDBOIDCError('This OIDC plugin instance has been destroyed and is no longer active', { codeName: 'PluginInstanceDestroyed' });
|
|
738
797
|
}
|
|
739
798
|
if (!params.idpInfo) {
|
|
740
|
-
throw new types_1.MongoDBOIDCError('No IdP information provided'
|
|
799
|
+
throw new types_1.MongoDBOIDCError('No IdP information provided', {
|
|
800
|
+
codeName: 'IdPInfoMissing',
|
|
801
|
+
});
|
|
741
802
|
}
|
|
742
803
|
const state = this.getAuthState({
|
|
743
804
|
...params.idpInfo,
|
|
744
805
|
username: params.username,
|
|
745
806
|
});
|
|
807
|
+
this.logger.emit('mongodb-oidc-plugin:request-token-started', {
|
|
808
|
+
authStateId: state.id,
|
|
809
|
+
isCurrentAuthAttemptSet: !!state.currentAuthAttempt,
|
|
810
|
+
tokenSetId: params.refreshToken,
|
|
811
|
+
username: state.serverOIDCMetadata.username,
|
|
812
|
+
issuer: state.serverOIDCMetadata.issuer,
|
|
813
|
+
clientId: state.serverOIDCMetadata.clientId,
|
|
814
|
+
requestScopes: state.serverOIDCMetadata.requestScopes,
|
|
815
|
+
});
|
|
746
816
|
// If the driver called us with a refresh token, that means that its corresponding
|
|
747
817
|
// access token has become invalid and we should always return a new one.
|
|
748
818
|
if (params.refreshToken) {
|
|
749
|
-
(state.discardingTokenSets
|
|
819
|
+
(state.discardingTokenSets ??= []).push(params.refreshToken);
|
|
750
820
|
this.logger.emit('mongodb-oidc-plugin:discarding-token-set', {
|
|
751
821
|
tokenSetId: params.refreshToken,
|
|
752
822
|
});
|
|
@@ -766,6 +836,15 @@ class MongoDBOIDCPluginImpl {
|
|
|
766
836
|
}
|
|
767
837
|
}
|
|
768
838
|
finally {
|
|
839
|
+
this.logger.emit('mongodb-oidc-plugin:request-token-ended', {
|
|
840
|
+
authStateId: state.id,
|
|
841
|
+
isCurrentAuthAttemptSet: !!state.currentAuthAttempt,
|
|
842
|
+
tokenSetId: params.refreshToken,
|
|
843
|
+
username: state.serverOIDCMetadata.username,
|
|
844
|
+
issuer: state.serverOIDCMetadata.issuer,
|
|
845
|
+
clientId: state.serverOIDCMetadata.clientId,
|
|
846
|
+
requestScopes: state.serverOIDCMetadata.requestScopes,
|
|
847
|
+
});
|
|
769
848
|
if (params.refreshToken) {
|
|
770
849
|
const index = state.discardingTokenSets?.indexOf(params.refreshToken) ?? -1;
|
|
771
850
|
if (index > 0) {
|
|
@@ -787,5 +866,4 @@ class MongoDBOIDCPluginImpl {
|
|
|
787
866
|
}
|
|
788
867
|
}
|
|
789
868
|
exports.MongoDBOIDCPluginImpl = MongoDBOIDCPluginImpl;
|
|
790
|
-
MongoDBOIDCPluginImpl.defaultRedirectURI = 'http://localhost:27097/redirect';
|
|
791
869
|
//# sourceMappingURL=plugin.js.map
|