mongodb 6.6.2 → 6.7.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/client-side-encryption/providers/azure.js +21 -6
- package/lib/client-side-encryption/providers/azure.js.map +1 -1
- package/lib/cmap/auth/mongo_credentials.js +24 -16
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js +78 -0
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +74 -0
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +74 -135
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/command_builders.js +45 -0
- package/lib/cmap/auth/mongodb_oidc/command_builders.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +46 -0
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js +122 -0
- package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js +107 -0
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/token_cache.js +52 -0
- package/lib/cmap/auth/mongodb_oidc/token_cache.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +34 -0
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc.js +26 -24
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/lib/cmap/auth/providers.js +0 -1
- package/lib/cmap/auth/providers.js.map +1 -1
- package/lib/cmap/connect.js +4 -4
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +1 -1
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/connection_string.js +3 -0
- package/lib/connection_string.js.map +1 -1
- package/lib/error.js +57 -2
- package/lib/error.js.map +1 -1
- package/lib/index.js +5 -3
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +1 -1
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_client_auth_providers.js +34 -4
- package/lib/mongo_client_auth_providers.js.map +1 -1
- package/lib/sdam/server_description.js +10 -4
- package/lib/sdam/server_description.js.map +1 -1
- package/lib/sessions.js +10 -0
- package/lib/sessions.js.map +1 -1
- package/lib/utils.js +32 -2
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +115 -25
- package/package.json +5 -4
- package/src/client-side-encryption/providers/azure.ts +21 -10
- package/src/cmap/auth/mongo_credentials.ts +41 -34
- package/src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts +82 -0
- package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +85 -0
- package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +96 -204
- package/src/cmap/auth/mongodb_oidc/command_builders.ts +54 -0
- package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +53 -0
- package/src/cmap/auth/mongodb_oidc/human_callback_workflow.ts +142 -0
- package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +137 -0
- package/src/cmap/auth/mongodb_oidc/token_cache.ts +62 -0
- package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +34 -0
- package/src/cmap/auth/mongodb_oidc.ts +79 -49
- package/src/cmap/auth/providers.ts +0 -1
- package/src/cmap/connect.ts +14 -4
- package/src/cmap/connection.ts +1 -0
- package/src/cmap/connection_pool.ts +2 -1
- package/src/connection_string.ts +3 -0
- package/src/error.ts +58 -1
- package/src/index.ts +8 -4
- package/src/mongo_client.ts +4 -1
- package/src/mongo_client_auth_providers.ts +44 -6
- package/src/sdam/server_description.ts +13 -4
- package/src/sessions.ts +10 -0
- package/src/utils.ts +33 -0
- package/lib/client-side-encryption/providers/utils.js +0 -35
- package/lib/client-side-encryption/providers/utils.js.map +0 -1
- package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js +0 -30
- package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js.map +0 -1
- package/lib/cmap/auth/mongodb_oidc/azure_service_workflow.js +0 -73
- package/lib/cmap/auth/mongodb_oidc/azure_service_workflow.js.map +0 -1
- package/lib/cmap/auth/mongodb_oidc/azure_token_cache.js +0 -49
- package/lib/cmap/auth/mongodb_oidc/azure_token_cache.js.map +0 -1
- package/lib/cmap/auth/mongodb_oidc/cache.js +0 -55
- package/lib/cmap/auth/mongodb_oidc/cache.js.map +0 -1
- package/lib/cmap/auth/mongodb_oidc/callback_lock_cache.js +0 -90
- package/lib/cmap/auth/mongodb_oidc/callback_lock_cache.js.map +0 -1
- package/lib/cmap/auth/mongodb_oidc/service_workflow.js +0 -43
- package/lib/cmap/auth/mongodb_oidc/service_workflow.js.map +0 -1
- package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js +0 -62
- package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js.map +0 -1
- package/src/client-side-encryption/providers/utils.ts +0 -37
- package/src/cmap/auth/mongodb_oidc/aws_service_workflow.ts +0 -29
- package/src/cmap/auth/mongodb_oidc/azure_service_workflow.ts +0 -86
- package/src/cmap/auth/mongodb_oidc/azure_token_cache.ts +0 -51
- package/src/cmap/auth/mongodb_oidc/cache.ts +0 -63
- package/src/cmap/auth/mongodb_oidc/callback_lock_cache.ts +0 -115
- package/src/cmap/auth/mongodb_oidc/service_workflow.ts +0 -49
- package/src/cmap/auth/mongodb_oidc/token_entry_cache.ts +0 -77
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadAzureCredentials = exports.fetchAzureKMSToken = exports.prepareRequest = exports.tokenCache = exports.AzureCredentialCache = void 0;
|
|
3
|
+
exports.loadAzureCredentials = exports.fetchAzureKMSToken = exports.prepareRequest = exports.addAzureParams = exports.tokenCache = exports.AzureCredentialCache = exports.AZURE_BASE_URL = void 0;
|
|
4
|
+
const error_1 = require("../../error");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
4
6
|
const errors_1 = require("../errors");
|
|
5
|
-
const utils_1 = require("./utils");
|
|
6
7
|
const MINIMUM_TOKEN_REFRESH_IN_MILLISECONDS = 6000;
|
|
8
|
+
/** Base URL for getting Azure tokens. */
|
|
9
|
+
exports.AZURE_BASE_URL = 'http://169.254.169.254/metadata/identity/oauth2/token?';
|
|
7
10
|
/**
|
|
8
11
|
* @internal
|
|
9
12
|
*/
|
|
@@ -66,6 +69,19 @@ async function parseResponse(response) {
|
|
|
66
69
|
expiresOnTimestamp: Date.now() + expiresInMS
|
|
67
70
|
};
|
|
68
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* @internal
|
|
74
|
+
* Get the Azure endpoint URL.
|
|
75
|
+
*/
|
|
76
|
+
function addAzureParams(url, resource, username) {
|
|
77
|
+
url.searchParams.append('api-version', '2018-02-01');
|
|
78
|
+
url.searchParams.append('resource', resource);
|
|
79
|
+
if (username) {
|
|
80
|
+
url.searchParams.append('client_id', username);
|
|
81
|
+
}
|
|
82
|
+
return url;
|
|
83
|
+
}
|
|
84
|
+
exports.addAzureParams = addAzureParams;
|
|
69
85
|
/**
|
|
70
86
|
* @internal
|
|
71
87
|
*
|
|
@@ -73,9 +89,8 @@ async function parseResponse(response) {
|
|
|
73
89
|
* the default values for headers and the request url.
|
|
74
90
|
*/
|
|
75
91
|
function prepareRequest(options) {
|
|
76
|
-
const url = new URL(options.url?.toString() ??
|
|
77
|
-
url
|
|
78
|
-
url.searchParams.append('resource', 'https://vault.azure.net');
|
|
92
|
+
const url = new URL(options.url?.toString() ?? exports.AZURE_BASE_URL);
|
|
93
|
+
addAzureParams(url, 'https://vault.azure.net');
|
|
79
94
|
const headers = { ...options.headers, 'Content-Type': 'application/json', Metadata: true };
|
|
80
95
|
return { headers, url };
|
|
81
96
|
}
|
|
@@ -97,7 +112,7 @@ async function fetchAzureKMSToken(options = {}) {
|
|
|
97
112
|
return await parseResponse(response);
|
|
98
113
|
}
|
|
99
114
|
catch (error) {
|
|
100
|
-
if (error instanceof
|
|
115
|
+
if (error instanceof error_1.MongoNetworkTimeoutError) {
|
|
101
116
|
throw new errors_1.MongoCryptAzureKMSRequestError(`[Azure KMS] ${error.message}`);
|
|
102
117
|
}
|
|
103
118
|
throw error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"azure.js","sourceRoot":"","sources":["../../../src/client-side-encryption/providers/azure.ts"],"names":[],"mappings":";;;AACA,
|
|
1
|
+
{"version":3,"file":"azure.js","sourceRoot":"","sources":["../../../src/client-side-encryption/providers/azure.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,11 +22,16 @@ function getDefaultAuthMechanism(hello) {
|
|
|
22
22
|
// Default for wireprotocol < 3
|
|
23
23
|
return providers_1.AuthMechanism.MONGODB_CR;
|
|
24
24
|
}
|
|
25
|
-
const
|
|
25
|
+
const ALLOWED_ENVIRONMENT_NAMES = [
|
|
26
|
+
'test',
|
|
27
|
+
'azure',
|
|
28
|
+
'gcp'
|
|
29
|
+
];
|
|
26
30
|
const ALLOWED_HOSTS_ERROR = 'Auth mechanism property ALLOWED_HOSTS must be an array of strings.';
|
|
27
31
|
/** @internal */
|
|
28
32
|
exports.DEFAULT_ALLOWED_HOSTS = [
|
|
29
33
|
'*.mongodb.net',
|
|
34
|
+
'*.mongodb-qa.net',
|
|
30
35
|
'*.mongodb-dev.net',
|
|
31
36
|
'*.mongodbgov.net',
|
|
32
37
|
'localhost',
|
|
@@ -34,7 +39,7 @@ exports.DEFAULT_ALLOWED_HOSTS = [
|
|
|
34
39
|
'::1'
|
|
35
40
|
];
|
|
36
41
|
/** Error for when the token audience is missing in the environment. */
|
|
37
|
-
const
|
|
42
|
+
const TOKEN_RESOURCE_MISSING_ERROR = 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure or gcp.';
|
|
38
43
|
/**
|
|
39
44
|
* A representation of the credentials used by MongoDB
|
|
40
45
|
* @public
|
|
@@ -109,24 +114,27 @@ class MongoCredentials {
|
|
|
109
114
|
throw new error_1.MongoMissingCredentialsError(`Username required for mechanism '${this.mechanism}'`);
|
|
110
115
|
}
|
|
111
116
|
if (this.mechanism === providers_1.AuthMechanism.MONGODB_OIDC) {
|
|
112
|
-
if (this.username &&
|
|
113
|
-
|
|
117
|
+
if (this.username &&
|
|
118
|
+
this.mechanismProperties.ENVIRONMENT &&
|
|
119
|
+
this.mechanismProperties.ENVIRONMENT !== 'azure') {
|
|
120
|
+
throw new error_1.MongoInvalidArgumentError(`username and ENVIRONMENT '${this.mechanismProperties.ENVIRONMENT}' may not be used together for mechanism '${this.mechanism}'.`);
|
|
114
121
|
}
|
|
115
|
-
if (this.
|
|
116
|
-
|
|
117
|
-
throw new error_1.MongoAzureError(TOKEN_AUDIENCE_MISSING_ERROR);
|
|
122
|
+
if (this.username && this.password) {
|
|
123
|
+
throw new error_1.MongoInvalidArgumentError(`No password is allowed in ENVIRONMENT '${this.mechanismProperties.ENVIRONMENT}' for '${this.mechanism}'.`);
|
|
118
124
|
}
|
|
119
|
-
if (this.mechanismProperties.
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
if ((this.mechanismProperties.ENVIRONMENT === 'azure' ||
|
|
126
|
+
this.mechanismProperties.ENVIRONMENT === 'gcp') &&
|
|
127
|
+
!this.mechanismProperties.TOKEN_RESOURCE) {
|
|
128
|
+
throw new error_1.MongoInvalidArgumentError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
122
129
|
}
|
|
123
|
-
if (this.mechanismProperties.
|
|
124
|
-
!this.mechanismProperties.
|
|
125
|
-
throw new error_1.MongoInvalidArgumentError(`
|
|
130
|
+
if (this.mechanismProperties.ENVIRONMENT &&
|
|
131
|
+
!ALLOWED_ENVIRONMENT_NAMES.includes(this.mechanismProperties.ENVIRONMENT)) {
|
|
132
|
+
throw new error_1.MongoInvalidArgumentError(`Currently only a ENVIRONMENT in ${ALLOWED_ENVIRONMENT_NAMES.join(',')} is supported for mechanism '${this.mechanism}'.`);
|
|
126
133
|
}
|
|
127
|
-
if (!this.mechanismProperties.
|
|
128
|
-
!this.mechanismProperties.
|
|
129
|
-
|
|
134
|
+
if (!this.mechanismProperties.ENVIRONMENT &&
|
|
135
|
+
!this.mechanismProperties.OIDC_CALLBACK &&
|
|
136
|
+
!this.mechanismProperties.OIDC_HUMAN_CALLBACK) {
|
|
137
|
+
throw new error_1.MongoInvalidArgumentError(`Either a ENVIRONMENT, OIDC_CALLBACK, or OIDC_HUMAN_CALLBACK must be specified for mechanism '${this.mechanism}'.`);
|
|
130
138
|
}
|
|
131
139
|
if (this.mechanismProperties.ALLOWED_HOSTS) {
|
|
132
140
|
const hosts = this.mechanismProperties.ALLOWED_HOSTS;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongo_credentials.js","sourceRoot":"","sources":["../../../src/cmap/auth/mongo_credentials.ts"],"names":[],"mappings":";;;AAGA,
|
|
1
|
+
{"version":3,"file":"mongo_credentials.js","sourceRoot":"","sources":["../../../src/cmap/auth/mongo_credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AutomatedCallbackWorkflow = void 0;
|
|
4
|
+
const error_1 = require("../../../error");
|
|
5
|
+
const timeout_1 = require("../../../timeout");
|
|
6
|
+
const mongodb_oidc_1 = require("../mongodb_oidc");
|
|
7
|
+
const callback_workflow_1 = require("./callback_workflow");
|
|
8
|
+
/**
|
|
9
|
+
* Class implementing behaviour for the non human callback workflow.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
class AutomatedCallbackWorkflow extends callback_workflow_1.CallbackWorkflow {
|
|
13
|
+
/**
|
|
14
|
+
* Instantiate the human callback workflow.
|
|
15
|
+
*/
|
|
16
|
+
constructor(cache, callback) {
|
|
17
|
+
super(cache, callback);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Execute the OIDC callback workflow.
|
|
21
|
+
*/
|
|
22
|
+
async execute(connection, credentials) {
|
|
23
|
+
// If there is a cached access token, try to authenticate with it. If
|
|
24
|
+
// authentication fails with an Authentication error (18),
|
|
25
|
+
// invalidate the access token, fetch a new access token, and try
|
|
26
|
+
// to authenticate again.
|
|
27
|
+
// If the server fails for any other reason, do not clear the cache.
|
|
28
|
+
if (this.cache.hasAccessToken) {
|
|
29
|
+
const token = this.cache.getAccessToken();
|
|
30
|
+
try {
|
|
31
|
+
return await this.finishAuthentication(connection, credentials, token);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof error_1.MongoError &&
|
|
35
|
+
error.code === error_1.MONGODB_ERROR_CODES.AuthenticationFailed) {
|
|
36
|
+
this.cache.removeAccessToken();
|
|
37
|
+
return await this.execute(connection, credentials);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const response = await this.fetchAccessToken(credentials);
|
|
45
|
+
this.cache.put(response);
|
|
46
|
+
connection.accessToken = response.accessToken;
|
|
47
|
+
await this.finishAuthentication(connection, credentials, response.accessToken);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Fetches the access token using the callback.
|
|
51
|
+
*/
|
|
52
|
+
async fetchAccessToken(credentials) {
|
|
53
|
+
const controller = new AbortController();
|
|
54
|
+
const params = {
|
|
55
|
+
timeoutContext: controller.signal,
|
|
56
|
+
version: mongodb_oidc_1.OIDC_VERSION
|
|
57
|
+
};
|
|
58
|
+
if (credentials.username) {
|
|
59
|
+
params.username = credentials.username;
|
|
60
|
+
}
|
|
61
|
+
const timeout = timeout_1.Timeout.expires(callback_workflow_1.AUTOMATED_TIMEOUT_MS);
|
|
62
|
+
try {
|
|
63
|
+
return await Promise.race([this.executeAndValidateCallback(params), timeout]);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (timeout_1.TimeoutError.is(error)) {
|
|
67
|
+
controller.abort();
|
|
68
|
+
throw new error_1.MongoOIDCError(`OIDC callback timed out after ${callback_workflow_1.AUTOMATED_TIMEOUT_MS}ms.`);
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
timeout.clear();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.AutomatedCallbackWorkflow = AutomatedCallbackWorkflow;
|
|
78
|
+
//# sourceMappingURL=automated_callback_workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automated_callback_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts"],"names":[],"mappings":";;;AAAA,0CAAiF;AACjF,8CAAyD;AAGzD,kDAKyB;AACzB,2DAA6E;AAG7E;;;GAGG;AACH,MAAa,yBAA0B,SAAQ,oCAAgB;IAC7D;;OAEG;IACH,YAAY,KAAiB,EAAE,QAA8B;QAC3D,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,UAAsB,EAAE,WAA6B;QACjE,qEAAqE;QACrE,0DAA0D;QAC1D,iEAAiE;QACjE,yBAAyB;QACzB,oEAAoE;QACpE,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAC1C,IAAI;gBACF,OAAO,MAAM,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;aACxE;YAAC,OAAO,KAAK,EAAE;gBACd,IACE,KAAK,YAAY,kBAAU;oBAC3B,KAAK,CAAC,IAAI,KAAK,2BAAmB,CAAC,oBAAoB,EACvD;oBACA,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;oBAC/B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;iBACpD;qBAAM;oBACL,MAAM,KAAK,CAAC;iBACb;aACF;SACF;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzB,UAAU,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;QAC9C,MAAM,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjF,CAAC;IAED;;OAEG;IACO,KAAK,CAAC,gBAAgB,CAAC,WAA6B;QAC5D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,MAAM,GAAuB;YACjC,cAAc,EAAE,UAAU,CAAC,MAAM;YACjC,OAAO,EAAE,2BAAY;SACtB,CAAC;QACF,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;SACxC;QACD,MAAM,OAAO,GAAG,iBAAO,CAAC,OAAO,CAAC,wCAAoB,CAAC,CAAC;QACtD,IAAI;YACF,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;SAC/E;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,sBAAY,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;gBAC1B,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnB,MAAM,IAAI,sBAAc,CAAC,iCAAiC,wCAAoB,KAAK,CAAC,CAAC;aACtF;YACD,MAAM,KAAK,CAAC;SACb;gBAAS;YACR,OAAO,CAAC,KAAK,EAAE,CAAC;SACjB;IACH,CAAC;CACF;AAhED,8DAgEC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AzureMachineWorkflow = void 0;
|
|
4
|
+
const azure_1 = require("../../../client-side-encryption/providers/azure");
|
|
5
|
+
const error_1 = require("../../../error");
|
|
6
|
+
const utils_1 = require("../../../utils");
|
|
7
|
+
const machine_workflow_1 = require("./machine_workflow");
|
|
8
|
+
/** Azure request headers. */
|
|
9
|
+
const AZURE_HEADERS = Object.freeze({ Metadata: 'true', Accept: 'application/json' });
|
|
10
|
+
/** Invalid endpoint result error. */
|
|
11
|
+
const ENDPOINT_RESULT_ERROR = 'Azure endpoint did not return a value with only access_token and expires_in properties';
|
|
12
|
+
/** Error for when the token audience is missing in the environment. */
|
|
13
|
+
const TOKEN_RESOURCE_MISSING_ERROR = 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure.';
|
|
14
|
+
/**
|
|
15
|
+
* Device workflow implementation for Azure.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
class AzureMachineWorkflow extends machine_workflow_1.MachineWorkflow {
|
|
20
|
+
/**
|
|
21
|
+
* Instantiate the machine workflow.
|
|
22
|
+
*/
|
|
23
|
+
constructor(cache) {
|
|
24
|
+
super(cache);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the token from the environment.
|
|
28
|
+
*/
|
|
29
|
+
async getToken(credentials) {
|
|
30
|
+
const tokenAudience = credentials?.mechanismProperties.TOKEN_RESOURCE;
|
|
31
|
+
const username = credentials?.username;
|
|
32
|
+
if (!tokenAudience) {
|
|
33
|
+
throw new error_1.MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
34
|
+
}
|
|
35
|
+
const response = await getAzureTokenData(tokenAudience, username);
|
|
36
|
+
if (!isEndpointResultValid(response)) {
|
|
37
|
+
throw new error_1.MongoAzureError(ENDPOINT_RESULT_ERROR);
|
|
38
|
+
}
|
|
39
|
+
return response;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.AzureMachineWorkflow = AzureMachineWorkflow;
|
|
43
|
+
/**
|
|
44
|
+
* Hit the Azure endpoint to get the token data.
|
|
45
|
+
*/
|
|
46
|
+
async function getAzureTokenData(tokenAudience, username) {
|
|
47
|
+
const url = new URL(azure_1.AZURE_BASE_URL);
|
|
48
|
+
(0, azure_1.addAzureParams)(url, tokenAudience, username);
|
|
49
|
+
const response = await (0, utils_1.get)(url, {
|
|
50
|
+
headers: AZURE_HEADERS
|
|
51
|
+
});
|
|
52
|
+
if (response.status !== 200) {
|
|
53
|
+
throw new error_1.MongoAzureError(`Status code ${response.status} returned from the Azure endpoint. Response body: ${response.body}`);
|
|
54
|
+
}
|
|
55
|
+
const result = JSON.parse(response.body);
|
|
56
|
+
return {
|
|
57
|
+
access_token: result.access_token,
|
|
58
|
+
expires_in: Number(result.expires_in)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Determines if a result returned from the endpoint is valid.
|
|
63
|
+
* This means the result is not nullish, contains the access_token required field
|
|
64
|
+
* and the expires_in required field.
|
|
65
|
+
*/
|
|
66
|
+
function isEndpointResultValid(token) {
|
|
67
|
+
if (token == null || typeof token !== 'object')
|
|
68
|
+
return false;
|
|
69
|
+
return ('access_token' in token &&
|
|
70
|
+
typeof token.access_token === 'string' &&
|
|
71
|
+
'expires_in' in token &&
|
|
72
|
+
typeof token.expires_in === 'number');
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=azure_machine_workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,2EAAiG;AACjG,0CAAiD;AACjD,0CAAqC;AAErC,yDAAuE;AAGvE,6BAA6B;AAC7B,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;AAEtF,qCAAqC;AACrC,MAAM,qBAAqB,GACzB,wFAAwF,CAAC;AAE3F,uEAAuE;AACvE,MAAM,4BAA4B,GAChC,wFAAwF,CAAC;AAE3F;;;;GAIG;AACH,MAAa,oBAAqB,SAAQ,kCAAe;IACvD;;OAEG;IACH,YAAY,KAAiB;QAC3B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,WAA8B;QAC3C,MAAM,aAAa,GAAG,WAAW,EAAE,mBAAmB,CAAC,cAAc,CAAC;QACtE,MAAM,QAAQ,GAAG,WAAW,EAAE,QAAQ,CAAC;QACvC,IAAI,CAAC,aAAa,EAAE;YAClB,MAAM,IAAI,uBAAe,CAAC,4BAA4B,CAAC,CAAC;SACzD;QACD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAClE,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE;YACpC,MAAM,IAAI,uBAAe,CAAC,qBAAqB,CAAC,CAAC;SAClD;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAvBD,oDAuBC;AAED;;GAEG;AACH,KAAK,UAAU,iBAAiB,CAAC,aAAqB,EAAE,QAAiB;IACvE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,sBAAc,CAAC,CAAC;IACpC,IAAA,sBAAc,EAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,IAAA,WAAG,EAAC,GAAG,EAAE;QAC9B,OAAO,EAAE,aAAa;KACvB,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE;QAC3B,MAAM,IAAI,uBAAe,CACvB,eAAe,QAAQ,CAAC,MAAM,qDAAqD,QAAQ,CAAC,IAAI,EAAE,CACnG,CAAC;KACH;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;KACtC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,qBAAqB,CAC5B,KAAc;IAEd,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC7D,OAAO,CACL,cAAc,IAAI,KAAK;QACvB,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ;QACtC,YAAY,IAAI,KAAK;QACrB,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,CACrC,CAAC;AACJ,CAAC"}
|
|
@@ -1,179 +1,133 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CallbackWorkflow = void 0;
|
|
4
|
-
const
|
|
3
|
+
exports.CallbackWorkflow = exports.AUTOMATED_TIMEOUT_MS = exports.HUMAN_TIMEOUT_MS = void 0;
|
|
4
|
+
const promises_1 = require("timers/promises");
|
|
5
5
|
const error_1 = require("../../../error");
|
|
6
6
|
const utils_1 = require("../../../utils");
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
/** 5 minutes in seconds */
|
|
13
|
-
const TIMEOUT_S = 300;
|
|
7
|
+
const command_builders_1 = require("./command_builders");
|
|
8
|
+
/** 5 minutes in milliseconds */
|
|
9
|
+
exports.HUMAN_TIMEOUT_MS = 300000;
|
|
10
|
+
/** 1 minute in milliseconds */
|
|
11
|
+
exports.AUTOMATED_TIMEOUT_MS = 60000;
|
|
14
12
|
/** Properties allowed on results of callbacks. */
|
|
15
13
|
const RESULT_PROPERTIES = ['accessToken', 'expiresInSeconds', 'refreshToken'];
|
|
16
14
|
/** Error message when the callback result is invalid. */
|
|
17
15
|
const CALLBACK_RESULT_ERROR = 'User provided OIDC callbacks must return a valid object with an accessToken.';
|
|
16
|
+
/** The time to throttle callback calls. */
|
|
17
|
+
const THROTTLE_MS = 100;
|
|
18
18
|
/**
|
|
19
19
|
* OIDC implementation of a callback based workflow.
|
|
20
20
|
* @internal
|
|
21
21
|
*/
|
|
22
22
|
class CallbackWorkflow {
|
|
23
23
|
/**
|
|
24
|
-
* Instantiate the workflow
|
|
24
|
+
* Instantiate the callback workflow.
|
|
25
25
|
*/
|
|
26
|
-
constructor() {
|
|
27
|
-
this.cache =
|
|
28
|
-
this.
|
|
26
|
+
constructor(cache, callback) {
|
|
27
|
+
this.cache = cache;
|
|
28
|
+
this.callback = this.withLock(callback);
|
|
29
|
+
this.lastExecutionTime = Date.now() - THROTTLE_MS;
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
31
32
|
* Get the document to add for speculative authentication. This also needs
|
|
32
33
|
* to add a db field from the credentials source.
|
|
33
34
|
*/
|
|
34
|
-
async speculativeAuth(credentials) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
async speculativeAuth(connection, credentials) {
|
|
36
|
+
// Check if the Client Cache has an access token.
|
|
37
|
+
// If it does, cache the access token in the Connection Cache and send a JwtStepRequest
|
|
38
|
+
// with the cached access token in the speculative authentication SASL payload.
|
|
39
|
+
if (this.cache.hasAccessToken) {
|
|
40
|
+
const accessToken = this.cache.getAccessToken();
|
|
41
|
+
connection.accessToken = accessToken;
|
|
42
|
+
const document = (0, command_builders_1.finishCommandDocument)(accessToken);
|
|
43
|
+
document.db = credentials.source;
|
|
44
|
+
return { speculativeAuthenticate: document };
|
|
45
|
+
}
|
|
46
|
+
return {};
|
|
38
47
|
}
|
|
39
48
|
/**
|
|
40
|
-
*
|
|
49
|
+
* Reauthenticate the callback workflow. For this we invalidated the access token
|
|
50
|
+
* in the cache and run the authentication steps again. No initial handshake needs
|
|
51
|
+
* to be sent.
|
|
41
52
|
*/
|
|
42
|
-
async
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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);
|
|
53
|
+
async reauthenticate(connection, credentials) {
|
|
54
|
+
if (this.cache.hasAccessToken) {
|
|
55
|
+
// Reauthentication implies the token has expired.
|
|
56
|
+
if (connection.accessToken === this.cache.getAccessToken()) {
|
|
57
|
+
// If connection's access token is the same as the cache's, remove
|
|
58
|
+
// the token from the cache and connection.
|
|
59
|
+
this.cache.removeAccessToken();
|
|
60
|
+
delete connection.accessToken;
|
|
54
61
|
}
|
|
55
62
|
else {
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
result = await this.finishAuthentication(connection, credentials, tokenResult, reauthenticating ? undefined : response?.speculativeAuthenticate?.conversationId);
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
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
|
-
}
|
|
75
|
-
}
|
|
63
|
+
// If the connection's access token is different from the cache's, set
|
|
64
|
+
// the cache's token on the connection and do not remove from the
|
|
65
|
+
// cache.
|
|
66
|
+
connection.accessToken = this.cache.getAccessToken();
|
|
76
67
|
}
|
|
77
68
|
}
|
|
78
|
-
|
|
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);
|
|
86
|
-
}
|
|
87
|
-
return result;
|
|
69
|
+
await this.execute(connection, credentials);
|
|
88
70
|
}
|
|
89
71
|
/**
|
|
90
72
|
* Starts the callback authentication process. If there is a speculative
|
|
91
73
|
* authentication document from the initial handshake, then we will use that
|
|
92
74
|
* value to get the issuer, otherwise we will send the saslStart command.
|
|
93
75
|
*/
|
|
94
|
-
async startAuthentication(connection, credentials,
|
|
76
|
+
async startAuthentication(connection, credentials, response) {
|
|
95
77
|
let result;
|
|
96
|
-
if (
|
|
78
|
+
if (response?.speculativeAuthenticate) {
|
|
97
79
|
result = response.speculativeAuthenticate;
|
|
98
80
|
}
|
|
99
81
|
else {
|
|
100
|
-
result = await connection.command((0, utils_1.ns)(credentials.source), startCommandDocument(credentials), undefined);
|
|
82
|
+
result = await connection.command((0, utils_1.ns)(credentials.source), (0, command_builders_1.startCommandDocument)(credentials), undefined);
|
|
101
83
|
}
|
|
102
84
|
return result;
|
|
103
85
|
}
|
|
104
86
|
/**
|
|
105
87
|
* Finishes the callback authentication process.
|
|
106
88
|
*/
|
|
107
|
-
async finishAuthentication(connection, credentials,
|
|
108
|
-
|
|
109
|
-
return result;
|
|
89
|
+
async finishAuthentication(connection, credentials, token, conversationId) {
|
|
90
|
+
await connection.command((0, utils_1.ns)(credentials.source), (0, command_builders_1.finishCommandDocument)(token, conversationId), undefined);
|
|
110
91
|
}
|
|
111
92
|
/**
|
|
112
|
-
*
|
|
113
|
-
* puts it in the cache.
|
|
93
|
+
* Executes the callback and validates the output.
|
|
114
94
|
*/
|
|
115
|
-
async
|
|
116
|
-
|
|
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
|
-
}
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
// With no token in the cache we use the request callback.
|
|
139
|
-
result = await requestCallback(serverInfo, context);
|
|
140
|
-
}
|
|
95
|
+
async executeAndValidateCallback(params) {
|
|
96
|
+
const result = await this.callback(params);
|
|
141
97
|
// Validate that the result returned by the callback is acceptable. If it is not
|
|
142
98
|
// we must clear the token result from the cache.
|
|
143
99
|
if (isCallbackResultInvalid(result)) {
|
|
144
|
-
this.cache.deleteEntry(connection.address, credentials.username, callbackHash);
|
|
145
100
|
throw new error_1.MongoMissingCredentialsError(CALLBACK_RESULT_ERROR);
|
|
146
101
|
}
|
|
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
102
|
return result;
|
|
152
103
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Ensure the callback is only executed one at a time and throttles the calls
|
|
106
|
+
* to every 100ms.
|
|
107
|
+
*/
|
|
108
|
+
withLock(callback) {
|
|
109
|
+
let lock = Promise.resolve();
|
|
110
|
+
return async (params) => {
|
|
111
|
+
// We do this to ensure that we would never return the result of the
|
|
112
|
+
// previous lock, only the current callback's value would get returned.
|
|
113
|
+
await lock;
|
|
114
|
+
lock = lock
|
|
115
|
+
// eslint-disable-next-line github/no-then
|
|
116
|
+
.catch(() => null)
|
|
117
|
+
// eslint-disable-next-line github/no-then
|
|
118
|
+
.then(async () => {
|
|
119
|
+
const difference = Date.now() - this.lastExecutionTime;
|
|
120
|
+
if (difference <= THROTTLE_MS) {
|
|
121
|
+
await (0, promises_1.setTimeout)(THROTTLE_MS - difference, { signal: params.timeoutContext });
|
|
122
|
+
}
|
|
123
|
+
this.lastExecutionTime = Date.now();
|
|
124
|
+
return await callback(params);
|
|
125
|
+
});
|
|
126
|
+
return await lock;
|
|
165
127
|
};
|
|
166
128
|
}
|
|
167
|
-
// saslContinue requires a conversationId in the command to be valid so in this
|
|
168
|
-
// case the server allows "step two" to actually be a saslStart with the token
|
|
169
|
-
// as the jwt since the use of the cached value has no correlating conversating
|
|
170
|
-
// on the particular connection.
|
|
171
|
-
return {
|
|
172
|
-
saslStart: 1,
|
|
173
|
-
mechanism: providers_1.AuthMechanism.MONGODB_OIDC,
|
|
174
|
-
payload: new bson_1.Binary(bson_1.BSON.serialize({ jwt: token }))
|
|
175
|
-
};
|
|
176
129
|
}
|
|
130
|
+
exports.CallbackWorkflow = CallbackWorkflow;
|
|
177
131
|
/**
|
|
178
132
|
* Determines if a result returned from a request or refresh callback
|
|
179
133
|
* function is invalid. This means the result is nullish, doesn't contain
|
|
@@ -186,19 +140,4 @@ function isCallbackResultInvalid(tokenResult) {
|
|
|
186
140
|
return true;
|
|
187
141
|
return !Object.getOwnPropertyNames(tokenResult).every(prop => RESULT_PROPERTIES.includes(prop));
|
|
188
142
|
}
|
|
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
|
-
}
|
|
204
143
|
//# sourceMappingURL=callback_workflow.js.map
|