mongodb 5.3.0 → 5.4.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/lib/admin.js +16 -0
- package/lib/admin.js.map +1 -1
- package/lib/cmap/auth/mongo_credentials.js +29 -2
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js +5 -3
- package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/cache.js +28 -0
- package/lib/cmap/auth/mongodb_oidc/cache.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/callback_lock_cache.js +83 -0
- package/lib/cmap/auth/mongodb_oidc/callback_lock_cache.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +138 -112
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/service_workflow.js +4 -2
- package/lib/cmap/auth/mongodb_oidc/service_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js +12 -56
- package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc.js +17 -13
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/lib/cmap/connection.js +12 -12
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/wire_protocol/constants.js +2 -2
- package/lib/cmap/wire_protocol/shared.js +2 -2
- package/lib/cmap/wire_protocol/shared.js.map +1 -1
- package/lib/collection.js +3 -0
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +8 -0
- package/lib/connection_string.js.map +1 -1
- package/lib/db.js +16 -0
- package/lib/db.js.map +1 -1
- package/lib/mongo_client.js +15 -0
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_logger.js +40 -6
- package/lib/mongo_logger.js.map +1 -1
- package/lib/operations/run_command.js.map +1 -1
- package/lib/operations/stats.js.map +1 -1
- package/lib/utils.js +16 -1
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +108 -24
- package/package.json +2 -2
- package/src/admin.ts +16 -0
- package/src/change_stream.ts +1 -1
- package/src/cmap/auth/mongo_credentials.ts +35 -2
- package/src/cmap/auth/mongodb_oidc/aws_service_workflow.ts +6 -3
- package/src/cmap/auth/mongodb_oidc/cache.ts +27 -0
- package/src/cmap/auth/mongodb_oidc/callback_lock_cache.ts +107 -0
- package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +208 -171
- package/src/cmap/auth/mongodb_oidc/service_workflow.ts +5 -3
- package/src/cmap/auth/mongodb_oidc/token_entry_cache.ts +17 -96
- package/src/cmap/auth/mongodb_oidc.ts +61 -37
- package/src/cmap/connection.ts +13 -12
- package/src/cmap/wire_protocol/constants.ts +2 -2
- package/src/cmap/wire_protocol/shared.ts +2 -3
- package/src/collection.ts +3 -0
- package/src/connection_string.ts +11 -0
- package/src/db.ts +16 -0
- package/src/index.ts +4 -3
- package/src/mongo_client.ts +26 -3
- package/src/mongo_logger.ts +42 -6
- package/src/operations/run_command.ts +40 -3
- package/src/operations/stats.ts +11 -2
- package/src/utils.ts +17 -0
- package/lib/cmap/auth/mongodb_oidc/workflow.js +0 -3
- package/lib/cmap/auth/mongodb_oidc/workflow.js.map +0 -1
- package/src/cmap/auth/mongodb_oidc/workflow.ts +0 -21
package/lib/admin.js
CHANGED
|
@@ -37,6 +37,22 @@ class Admin {
|
|
|
37
37
|
/**
|
|
38
38
|
* Execute a command
|
|
39
39
|
*
|
|
40
|
+
* The driver will ensure the following fields are attached to the command sent to the server:
|
|
41
|
+
* - `lsid` - sourced from an implicit session or options.session
|
|
42
|
+
* - `$readPreference` - defaults to primary or can be configured by options.readPreference
|
|
43
|
+
* - `$db` - sourced from the name of this database
|
|
44
|
+
*
|
|
45
|
+
* If the client has a serverApi setting:
|
|
46
|
+
* - `apiVersion`
|
|
47
|
+
* - `apiStrict`
|
|
48
|
+
* - `apiDeprecationErrors`
|
|
49
|
+
*
|
|
50
|
+
* When in a transaction:
|
|
51
|
+
* - `readConcern` - sourced from readConcern set on the TransactionOptions
|
|
52
|
+
* - `writeConcern` - sourced from writeConcern set on the TransactionOptions
|
|
53
|
+
*
|
|
54
|
+
* Attaching any of the above fields to the command will have no effect as the driver will overwrite the value.
|
|
55
|
+
*
|
|
40
56
|
* @param command - The command to execute
|
|
41
57
|
* @param options - Optional settings for the command
|
|
42
58
|
*/
|
package/lib/admin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":";;;AAEA,oDAAyE;AAEzE,sEAAkE;AAClE,gEAIqC;AACrC,0DAAkF;AAClF,0DAAkF;AAClF,0EAG0C;AAO1C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAa,KAAK;IAIhB;;;OAGG;IACH,YAAY,EAAM;QAChB,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC;IAClB,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MongoCredentials = void 0;
|
|
3
|
+
exports.MongoCredentials = exports.DEFAULT_ALLOWED_HOSTS = void 0;
|
|
4
4
|
const error_1 = require("../../error");
|
|
5
5
|
const gssapi_1 = require("./gssapi");
|
|
6
6
|
const providers_1 = require("./providers");
|
|
@@ -22,13 +22,23 @@ function getDefaultAuthMechanism(hello) {
|
|
|
22
22
|
// Default for wireprotocol < 3
|
|
23
23
|
return providers_1.AuthMechanism.MONGODB_CR;
|
|
24
24
|
}
|
|
25
|
+
const ALLOWED_HOSTS_ERROR = 'Auth mechanism property ALLOWED_HOSTS must be an array of strings.';
|
|
26
|
+
/** @internal */
|
|
27
|
+
exports.DEFAULT_ALLOWED_HOSTS = [
|
|
28
|
+
'*.mongodb.net',
|
|
29
|
+
'*.mongodb-dev.net',
|
|
30
|
+
'*.mongodbgov.net',
|
|
31
|
+
'localhost',
|
|
32
|
+
'127.0.0.1',
|
|
33
|
+
'::1'
|
|
34
|
+
];
|
|
25
35
|
/**
|
|
26
36
|
* A representation of the credentials used by MongoDB
|
|
27
37
|
* @public
|
|
28
38
|
*/
|
|
29
39
|
class MongoCredentials {
|
|
30
40
|
constructor(options) {
|
|
31
|
-
this.username = options.username;
|
|
41
|
+
this.username = options.username ?? '';
|
|
32
42
|
this.password = options.password;
|
|
33
43
|
this.source = options.source;
|
|
34
44
|
if (!this.source && options.db) {
|
|
@@ -51,6 +61,12 @@ class MongoCredentials {
|
|
|
51
61
|
};
|
|
52
62
|
}
|
|
53
63
|
}
|
|
64
|
+
if (this.mechanism === providers_1.AuthMechanism.MONGODB_OIDC && !this.mechanismProperties.ALLOWED_HOSTS) {
|
|
65
|
+
this.mechanismProperties = {
|
|
66
|
+
...this.mechanismProperties,
|
|
67
|
+
ALLOWED_HOSTS: exports.DEFAULT_ALLOWED_HOSTS
|
|
68
|
+
};
|
|
69
|
+
}
|
|
54
70
|
Object.freeze(this.mechanismProperties);
|
|
55
71
|
Object.freeze(this);
|
|
56
72
|
}
|
|
@@ -105,6 +121,17 @@ class MongoCredentials {
|
|
|
105
121
|
!this.mechanismProperties.REQUEST_TOKEN_CALLBACK) {
|
|
106
122
|
throw new error_1.MongoInvalidArgumentError(`Either a PROVIDER_NAME or a REQUEST_TOKEN_CALLBACK must be specified for mechanism '${this.mechanism}'.`);
|
|
107
123
|
}
|
|
124
|
+
if (this.mechanismProperties.ALLOWED_HOSTS) {
|
|
125
|
+
const hosts = this.mechanismProperties.ALLOWED_HOSTS;
|
|
126
|
+
if (!Array.isArray(hosts)) {
|
|
127
|
+
throw new error_1.MongoInvalidArgumentError(ALLOWED_HOSTS_ERROR);
|
|
128
|
+
}
|
|
129
|
+
for (const host of hosts) {
|
|
130
|
+
if (typeof host !== 'string') {
|
|
131
|
+
throw new error_1.MongoInvalidArgumentError(ALLOWED_HOSTS_ERROR);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
108
135
|
}
|
|
109
136
|
if (providers_1.AUTH_MECHS_AUTH_SRC_EXTERNAL.has(this.mechanism)) {
|
|
110
137
|
if (this.source != null && this.source !== '$external') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongo_credentials.js","sourceRoot":"","sources":["../../../src/cmap/auth/mongo_credentials.ts"],"names":[],"mappings":";;;AAEA,uCAIqB;AACrB,qCAAuD;AAEvD,2CAA0E;AAE1E,6EAA6E;AAC7E,SAAS,uBAAuB,CAAC,KAAgB;IAC/C,IAAI,KAAK,EAAE;QACT,0DAA0D;QAC1D,uCAAuC;QACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE;YAC3C,OAAO,KAAK,CAAC,kBAAkB,CAAC,QAAQ,CAAC,yBAAa,CAAC,oBAAoB,CAAC;gBAC1E,CAAC,CAAC,yBAAa,CAAC,oBAAoB;gBACpC,CAAC,CAAC,yBAAa,CAAC,kBAAkB,CAAC;SACtC;QAED,6EAA6E;QAC7E,IAAI,KAAK,CAAC,cAAc,IAAI,CAAC,EAAE;YAC7B,OAAO,yBAAa,CAAC,kBAAkB,CAAC;SACzC;KACF;IAED,+BAA+B;IAC/B,OAAO,yBAAa,CAAC,UAAU,CAAC;AAClC,CAAC;
|
|
1
|
+
{"version":3,"file":"mongo_credentials.js","sourceRoot":"","sources":["../../../src/cmap/auth/mongo_credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AwsServiceWorkflow = void 0;
|
|
4
|
-
const
|
|
4
|
+
const fs = require("fs");
|
|
5
5
|
const error_1 = require("../../../error");
|
|
6
6
|
const service_workflow_1 = require("./service_workflow");
|
|
7
|
+
/** Error for when the token is missing in the environment. */
|
|
8
|
+
const TOKEN_MISSING_ERROR = 'AWS_WEB_IDENTITY_TOKEN_FILE must be set in the environment.';
|
|
7
9
|
/**
|
|
8
10
|
* Device workflow implementation for AWS.
|
|
9
11
|
*
|
|
@@ -19,9 +21,9 @@ class AwsServiceWorkflow extends service_workflow_1.ServiceWorkflow {
|
|
|
19
21
|
async getToken() {
|
|
20
22
|
const tokenFile = process.env.AWS_WEB_IDENTITY_TOKEN_FILE;
|
|
21
23
|
if (!tokenFile) {
|
|
22
|
-
throw new error_1.MongoAWSError(
|
|
24
|
+
throw new error_1.MongoAWSError(TOKEN_MISSING_ERROR);
|
|
23
25
|
}
|
|
24
|
-
return
|
|
26
|
+
return fs.promises.readFile(tokenFile, 'utf8');
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
exports.AwsServiceWorkflow = AwsServiceWorkflow;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aws_service_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/aws_service_workflow.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"aws_service_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/aws_service_workflow.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AAEzB,0CAA+C;AAC/C,yDAAqD;AAErD,8DAA8D;AAC9D,MAAM,mBAAmB,GAAG,6DAA6D,CAAC;AAE1F;;;;GAIG;AACH,MAAa,kBAAmB,SAAQ,kCAAe;IACrD;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;QAC1D,IAAI,CAAC,SAAS,EAAE;YACd,MAAM,IAAI,qBAAa,CAAC,mBAAmB,CAAC,CAAC;SAC9C;QACD,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;CACF;AAfD,gDAeC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Cache = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Base class for OIDC caches.
|
|
6
|
+
*/
|
|
7
|
+
class Cache {
|
|
8
|
+
/**
|
|
9
|
+
* Create a new cache.
|
|
10
|
+
*/
|
|
11
|
+
constructor() {
|
|
12
|
+
this.entries = new Map();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Clear the cache.
|
|
16
|
+
*/
|
|
17
|
+
clear() {
|
|
18
|
+
this.entries.clear();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a cache key from the address and username.
|
|
22
|
+
*/
|
|
23
|
+
cacheKey(address, username, callbackHash) {
|
|
24
|
+
return JSON.stringify([address, username, callbackHash]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.Cache = Cache;
|
|
28
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/cache.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAsB,KAAK;IAGzB;;OAEG;IACH;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAa,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,OAAe,EAAE,QAAgB,EAAE,YAAoB;QAC9D,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AAvBD,sBAuBC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CallbackLockCache = void 0;
|
|
4
|
+
const error_1 = require("../../../error");
|
|
5
|
+
const cache_1 = require("./cache");
|
|
6
|
+
/** Error message for when request callback is missing. */
|
|
7
|
+
const REQUEST_CALLBACK_REQUIRED_ERROR = 'Auth mechanism property REQUEST_TOKEN_CALLBACK is required.';
|
|
8
|
+
/* Counter for function "hashes".*/
|
|
9
|
+
let FN_HASH_COUNTER = 0;
|
|
10
|
+
/* No function present function */
|
|
11
|
+
const NO_FUNCTION = async () => ({ accessToken: 'test' });
|
|
12
|
+
/* The map of function hashes */
|
|
13
|
+
const FN_HASHES = new WeakMap();
|
|
14
|
+
/* Put the no function hash in the map. */
|
|
15
|
+
FN_HASHES.set(NO_FUNCTION, FN_HASH_COUNTER);
|
|
16
|
+
/**
|
|
17
|
+
* A cache of request and refresh callbacks per server/user.
|
|
18
|
+
*/
|
|
19
|
+
class CallbackLockCache extends cache_1.Cache {
|
|
20
|
+
/**
|
|
21
|
+
* Get the callbacks for the connection and credentials. If an entry does not
|
|
22
|
+
* exist a new one will get set.
|
|
23
|
+
*/
|
|
24
|
+
getCallbacks(connection, credentials) {
|
|
25
|
+
const requestCallback = credentials.mechanismProperties.REQUEST_TOKEN_CALLBACK;
|
|
26
|
+
const refreshCallback = credentials.mechanismProperties.REFRESH_TOKEN_CALLBACK;
|
|
27
|
+
if (!requestCallback) {
|
|
28
|
+
throw new error_1.MongoInvalidArgumentError(REQUEST_CALLBACK_REQUIRED_ERROR);
|
|
29
|
+
}
|
|
30
|
+
const callbackHash = hashFunctions(requestCallback, refreshCallback);
|
|
31
|
+
const key = this.cacheKey(connection.address, credentials.username, callbackHash);
|
|
32
|
+
const entry = this.entries.get(key);
|
|
33
|
+
if (entry) {
|
|
34
|
+
return entry;
|
|
35
|
+
}
|
|
36
|
+
return this.setCallbacks(key, callbackHash, requestCallback, refreshCallback);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Set locked callbacks on for connection and credentials.
|
|
40
|
+
*/
|
|
41
|
+
setCallbacks(key, callbackHash, requestCallback, refreshCallback) {
|
|
42
|
+
const entry = {
|
|
43
|
+
requestCallback: withLock(requestCallback),
|
|
44
|
+
refreshCallback: refreshCallback ? withLock(refreshCallback) : undefined,
|
|
45
|
+
callbackHash: callbackHash
|
|
46
|
+
};
|
|
47
|
+
this.entries.set(key, entry);
|
|
48
|
+
return entry;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.CallbackLockCache = CallbackLockCache;
|
|
52
|
+
/**
|
|
53
|
+
* Ensure the callback is only executed one at a time.
|
|
54
|
+
*/
|
|
55
|
+
function withLock(callback) {
|
|
56
|
+
let lock = Promise.resolve();
|
|
57
|
+
return async (info, context) => {
|
|
58
|
+
await lock;
|
|
59
|
+
lock = lock.then(() => callback(info, context));
|
|
60
|
+
return lock;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the hash string for the request and refresh functions.
|
|
65
|
+
*/
|
|
66
|
+
function hashFunctions(requestFn, refreshFn) {
|
|
67
|
+
let requestHash = FN_HASHES.get(requestFn);
|
|
68
|
+
let refreshHash = FN_HASHES.get(refreshFn ?? NO_FUNCTION);
|
|
69
|
+
if (requestHash == null) {
|
|
70
|
+
// Create a new one for the function and put it in the map.
|
|
71
|
+
FN_HASH_COUNTER++;
|
|
72
|
+
requestHash = FN_HASH_COUNTER;
|
|
73
|
+
FN_HASHES.set(requestFn, FN_HASH_COUNTER);
|
|
74
|
+
}
|
|
75
|
+
if (refreshHash == null && refreshFn) {
|
|
76
|
+
// Create a new one for the function and put it in the map.
|
|
77
|
+
FN_HASH_COUNTER++;
|
|
78
|
+
refreshHash = FN_HASH_COUNTER;
|
|
79
|
+
FN_HASHES.set(refreshFn, FN_HASH_COUNTER);
|
|
80
|
+
}
|
|
81
|
+
return `${requestHash}-${refreshHash}`;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=callback_lock_cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback_lock_cache.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/callback_lock_cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,9 +5,16 @@ const bson_1 = require("bson");
|
|
|
5
5
|
const error_1 = require("../../../error");
|
|
6
6
|
const utils_1 = require("../../../utils");
|
|
7
7
|
const providers_1 = require("../providers");
|
|
8
|
+
const callback_lock_cache_1 = require("./callback_lock_cache");
|
|
8
9
|
const token_entry_cache_1 = require("./token_entry_cache");
|
|
9
|
-
|
|
10
|
-
const
|
|
10
|
+
/** The current version of OIDC implementation. */
|
|
11
|
+
const OIDC_VERSION = 0;
|
|
12
|
+
/** 5 minutes in seconds */
|
|
13
|
+
const TIMEOUT_S = 300;
|
|
14
|
+
/** Properties allowed on results of callbacks. */
|
|
15
|
+
const RESULT_PROPERTIES = ['accessToken', 'expiresInSeconds', 'refreshToken'];
|
|
16
|
+
/** Error message when the callback result is invalid. */
|
|
17
|
+
const CALLBACK_RESULT_ERROR = 'User provided OIDC callbacks must return a valid object with an accessToken.';
|
|
11
18
|
/**
|
|
12
19
|
* OIDC implementation of a callback based workflow.
|
|
13
20
|
* @internal
|
|
@@ -18,147 +25,139 @@ class CallbackWorkflow {
|
|
|
18
25
|
*/
|
|
19
26
|
constructor() {
|
|
20
27
|
this.cache = new token_entry_cache_1.TokenEntryCache();
|
|
28
|
+
this.callbackCache = new callback_lock_cache_1.CallbackLockCache();
|
|
21
29
|
}
|
|
22
30
|
/**
|
|
23
|
-
* Get the document to add for speculative authentication.
|
|
24
|
-
*
|
|
31
|
+
* Get the document to add for speculative authentication. This also needs
|
|
32
|
+
* to add a db field from the credentials source.
|
|
25
33
|
*/
|
|
26
|
-
speculativeAuth() {
|
|
27
|
-
|
|
34
|
+
async speculativeAuth(credentials) {
|
|
35
|
+
const document = startCommandDocument(credentials);
|
|
36
|
+
document.db = credentials.source;
|
|
37
|
+
return { speculativeAuthenticate: document };
|
|
28
38
|
}
|
|
29
39
|
/**
|
|
30
|
-
* Execute the workflow.
|
|
31
|
-
*
|
|
32
|
-
* Steps:
|
|
33
|
-
* - If an entry is in the cache
|
|
34
|
-
* - If it is not expired
|
|
35
|
-
* - Skip step one and use the entry to execute step two.
|
|
36
|
-
* - If it is expired
|
|
37
|
-
* - If the refresh callback exists
|
|
38
|
-
* - remove expired entry from cache
|
|
39
|
-
* - call the refresh callback.
|
|
40
|
-
* - put the new entry in the cache.
|
|
41
|
-
* - execute step two.
|
|
42
|
-
* - If the refresh callback does not exist.
|
|
43
|
-
* - remove expired entry from cache
|
|
44
|
-
* - call the request callback.
|
|
45
|
-
* - put the new entry in the cache.
|
|
46
|
-
* - execute step two.
|
|
47
|
-
* - If no entry is in the cache.
|
|
48
|
-
* - execute step one.
|
|
49
|
-
* - call the refresh callback.
|
|
50
|
-
* - put the new entry in the cache.
|
|
51
|
-
* - execute step two.
|
|
40
|
+
* Execute the OIDC callback workflow.
|
|
52
41
|
*/
|
|
53
|
-
async execute(connection, credentials,
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
42
|
+
async execute(connection, credentials, reauthenticating, response) {
|
|
43
|
+
// Get the callbacks with locks from the callback lock cache.
|
|
44
|
+
const { requestCallback, refreshCallback, callbackHash } = this.callbackCache.getCallbacks(connection, credentials);
|
|
45
|
+
// Look for an existing entry in the cache.
|
|
46
|
+
const entry = this.cache.getEntry(connection.address, credentials.username, callbackHash);
|
|
47
|
+
let result;
|
|
57
48
|
if (entry) {
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
// Reauthentication cannot use a token from the cache since the server has
|
|
50
|
+
// stated it is invalid by the request for reauthentication.
|
|
51
|
+
if (entry.isValid() && !reauthenticating) {
|
|
52
|
+
// Presence of a valid cache entry means we can skip to the finishing step.
|
|
53
|
+
result = await this.finishAuthentication(connection, credentials, entry.tokenResult, response?.speculativeAuthenticate?.conversationId);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Presence of an expired cache entry means we must fetch a new one and
|
|
57
|
+
// then execute the final step.
|
|
58
|
+
const tokenResult = await this.fetchAccessToken(connection, credentials, entry.serverInfo, reauthenticating, callbackHash, requestCallback, refreshCallback);
|
|
61
59
|
try {
|
|
62
|
-
|
|
63
|
-
return result;
|
|
60
|
+
result = await this.finishAuthentication(connection, credentials, tokenResult, reauthenticating ? undefined : response?.speculativeAuthenticate?.conversationId);
|
|
64
61
|
}
|
|
65
62
|
catch (error) {
|
|
66
|
-
// If
|
|
67
|
-
// the
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
// If we are reauthenticating and this errors with reauthentication
|
|
64
|
+
// required, we need to do the entire process over again and clear
|
|
65
|
+
// the cache entry.
|
|
66
|
+
if (reauthenticating &&
|
|
67
|
+
error instanceof error_1.MongoError &&
|
|
68
|
+
error.code === error_1.MONGODB_ERROR_CODES.Reauthenticate) {
|
|
69
|
+
this.cache.deleteEntry(connection.address, credentials.username, callbackHash);
|
|
70
|
+
result = await this.execute(connection, credentials, reauthenticating);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
|
-
else {
|
|
73
|
-
// Remove the expired entry from the cache.
|
|
74
|
-
this.cache.deleteEntry(connection.address, credentials.username || '', request || null, refresh || null);
|
|
75
|
-
// Execute a refresh of the token and finish auth.
|
|
76
|
-
return this.refreshAndFinish(connection, credentials, entry.serverResult, entry.tokenResult);
|
|
77
|
-
}
|
|
78
77
|
}
|
|
79
78
|
else {
|
|
80
|
-
// No entry
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
// No entry in the cache requires us to do all authentication steps
|
|
80
|
+
// from start to finish, including getting a fresh token for the cache.
|
|
81
|
+
const startDocument = await this.startAuthentication(connection, credentials, reauthenticating, response);
|
|
82
|
+
const conversationId = startDocument.conversationId;
|
|
83
|
+
const serverResult = bson_1.BSON.deserialize(startDocument.payload.buffer);
|
|
84
|
+
const tokenResult = await this.fetchAccessToken(connection, credentials, serverResult, reauthenticating, callbackHash, requestCallback, refreshCallback);
|
|
85
|
+
result = await this.finishAuthentication(connection, credentials, tokenResult, conversationId);
|
|
85
86
|
}
|
|
87
|
+
return result;
|
|
86
88
|
}
|
|
87
89
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
+
* Starts the callback authentication process. If there is a speculative
|
|
91
|
+
* authentication document from the initial handshake, then we will use that
|
|
92
|
+
* value to get the issuer, otherwise we will send the saslStart command.
|
|
90
93
|
*/
|
|
91
|
-
async
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (refresh) {
|
|
96
|
-
const result = await refresh(credentials.username, stepOneResult, tokenResult, TIMEOUT_MS);
|
|
97
|
-
// Validate the result.
|
|
98
|
-
if (!result || !result.accessToken) {
|
|
99
|
-
throw new error_1.MongoMissingCredentialsError('REFRESH_TOKEN_CALLBACK must return a valid object with an accessToken');
|
|
100
|
-
}
|
|
101
|
-
// Cache a new entry and continue with the saslContinue.
|
|
102
|
-
this.cache.addEntry(connection.address, credentials.username || '', request || null, refresh, result, stepOneResult);
|
|
103
|
-
return finishAuth(result, conversationId, connection, credentials);
|
|
94
|
+
async startAuthentication(connection, credentials, reauthenticating, response) {
|
|
95
|
+
let result;
|
|
96
|
+
if (!reauthenticating && response?.speculativeAuthenticate) {
|
|
97
|
+
result = response.speculativeAuthenticate;
|
|
104
98
|
}
|
|
105
99
|
else {
|
|
106
|
-
|
|
107
|
-
return this.requestAndFinish(connection, credentials, stepOneResult, conversationId);
|
|
100
|
+
result = await connection.commandAsync((0, utils_1.ns)(credentials.source), startCommandDocument(credentials), undefined);
|
|
108
101
|
}
|
|
102
|
+
return result;
|
|
109
103
|
}
|
|
110
104
|
/**
|
|
111
|
-
*
|
|
105
|
+
* Finishes the callback authentication process.
|
|
112
106
|
*/
|
|
113
|
-
async
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
107
|
+
async finishAuthentication(connection, credentials, tokenResult, conversationId) {
|
|
108
|
+
const result = await connection.commandAsync((0, utils_1.ns)(credentials.source), finishCommandDocument(tokenResult.accessToken, conversationId), undefined);
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Fetches an access token using either the request or refresh callbacks and
|
|
113
|
+
* puts it in the cache.
|
|
114
|
+
*/
|
|
115
|
+
async fetchAccessToken(connection, credentials, serverInfo, reauthenticating, callbackHash, requestCallback, refreshCallback) {
|
|
116
|
+
// Get the token from the cache.
|
|
117
|
+
const entry = this.cache.getEntry(connection.address, credentials.username, callbackHash);
|
|
118
|
+
let result;
|
|
119
|
+
const context = { timeoutSeconds: TIMEOUT_S, version: OIDC_VERSION };
|
|
120
|
+
// Check if there's a token in the cache.
|
|
121
|
+
if (entry) {
|
|
122
|
+
// If the cache entry is valid, return the token result.
|
|
123
|
+
if (entry.isValid() && !reauthenticating) {
|
|
124
|
+
return entry.tokenResult;
|
|
125
|
+
}
|
|
126
|
+
// If the cache entry is not valid, remove it from the cache and first attempt
|
|
127
|
+
// to use the refresh callback to get a new token. If no refresh callback
|
|
128
|
+
// exists, then fallback to the request callback.
|
|
129
|
+
if (refreshCallback) {
|
|
130
|
+
context.refreshToken = entry.tokenResult.refreshToken;
|
|
131
|
+
result = await refreshCallback(serverInfo, context);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
result = await requestCallback(serverInfo, context);
|
|
135
|
+
}
|
|
122
136
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
137
|
+
else {
|
|
138
|
+
// With no token in the cache we use the request callback.
|
|
139
|
+
result = await requestCallback(serverInfo, context);
|
|
140
|
+
}
|
|
141
|
+
// Validate that the result returned by the callback is acceptable. If it is not
|
|
142
|
+
// we must clear the token result from the cache.
|
|
143
|
+
if (isCallbackResultInvalid(result)) {
|
|
144
|
+
this.cache.deleteEntry(connection.address, credentials.username, callbackHash);
|
|
145
|
+
throw new error_1.MongoMissingCredentialsError(CALLBACK_RESULT_ERROR);
|
|
127
146
|
}
|
|
128
|
-
//
|
|
129
|
-
this.cache.
|
|
130
|
-
|
|
147
|
+
// Cleanup the cache.
|
|
148
|
+
this.cache.deleteExpiredEntries();
|
|
149
|
+
// Put the new entry into the cache.
|
|
150
|
+
this.cache.addEntry(connection.address, credentials.username || '', callbackHash, result, serverInfo);
|
|
151
|
+
return result;
|
|
131
152
|
}
|
|
132
153
|
}
|
|
133
154
|
exports.CallbackWorkflow = CallbackWorkflow;
|
|
134
155
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*/
|
|
138
|
-
async function finishAuth(result, conversationId, connection, credentials) {
|
|
139
|
-
// Execute the step two saslContinue.
|
|
140
|
-
return connection.commandAsync((0, utils_1.ns)(credentials.source), continueCommandDocument(result.accessToken, conversationId), undefined);
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Generate the saslStart command document.
|
|
156
|
+
* Generate the finishing command document for authentication. Will be a
|
|
157
|
+
* saslStart or saslContinue depending on the presence of a conversation id.
|
|
144
158
|
*/
|
|
145
|
-
function
|
|
146
|
-
|
|
147
|
-
if (credentials.username) {
|
|
148
|
-
payload.n = credentials.username;
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
saslStart: 1,
|
|
152
|
-
autoAuthorize: 1,
|
|
153
|
-
mechanism: providers_1.AuthMechanism.MONGODB_OIDC,
|
|
154
|
-
payload: new bson_1.Binary(bson_1.BSON.serialize(payload))
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Generate the saslContinue command document.
|
|
159
|
-
*/
|
|
160
|
-
function continueCommandDocument(token, conversationId) {
|
|
161
|
-
if (conversationId) {
|
|
159
|
+
function finishCommandDocument(token, conversationId) {
|
|
160
|
+
if (conversationId != null && typeof conversationId === 'number') {
|
|
162
161
|
return {
|
|
163
162
|
saslContinue: 1,
|
|
164
163
|
conversationId: conversationId,
|
|
@@ -175,4 +174,31 @@ function continueCommandDocument(token, conversationId) {
|
|
|
175
174
|
payload: new bson_1.Binary(bson_1.BSON.serialize({ jwt: token }))
|
|
176
175
|
};
|
|
177
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Determines if a result returned from a request or refresh callback
|
|
179
|
+
* function is invalid. This means the result is nullish, doesn't contain
|
|
180
|
+
* the accessToken required field, and does not contain extra fields.
|
|
181
|
+
*/
|
|
182
|
+
function isCallbackResultInvalid(tokenResult) {
|
|
183
|
+
if (tokenResult == null || typeof tokenResult !== 'object')
|
|
184
|
+
return true;
|
|
185
|
+
if (!('accessToken' in tokenResult))
|
|
186
|
+
return true;
|
|
187
|
+
return !Object.getOwnPropertyNames(tokenResult).every(prop => RESULT_PROPERTIES.includes(prop));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Generate the saslStart command document.
|
|
191
|
+
*/
|
|
192
|
+
function startCommandDocument(credentials) {
|
|
193
|
+
const payload = {};
|
|
194
|
+
if (credentials.username) {
|
|
195
|
+
payload.n = credentials.username;
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
saslStart: 1,
|
|
199
|
+
autoAuthorize: 1,
|
|
200
|
+
mechanism: providers_1.AuthMechanism.MONGODB_OIDC,
|
|
201
|
+
payload: new bson_1.Binary(bson_1.BSON.serialize(payload))
|
|
202
|
+
};
|
|
203
|
+
}
|
|
178
204
|
//# sourceMappingURL=callback_workflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callback_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/callback_workflow.ts"],"names":[],"mappings":";;;AAAA,+BAAmD;AAEnD,
|
|
1
|
+
{"version":3,"file":"callback_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/callback_workflow.ts"],"names":[],"mappings":"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"}
|