mongodb 6.16.0-dev.20250531.sha.7ef6edd5 → 6.16.0-dev.20250603.sha.352b7ea6
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/beta.d.ts +2 -0
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js +6 -0
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +21 -33
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +14 -21
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +19 -26
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +12 -24
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc.js +5 -4
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/mongodb.d.ts +2 -0
- package/package.json +1 -1
- package/src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts +6 -0
- package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +23 -35
- package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +16 -23
- package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +17 -25
- package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +11 -24
- package/src/cmap/auth/mongodb_oidc.ts +13 -8
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js +0 -110
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js.map +0 -1
- package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +0 -142
package/lib/beta.d.ts
CHANGED
|
@@ -7474,6 +7474,8 @@ export declare interface OIDCCallbackParams {
|
|
|
7474
7474
|
idpInfo?: IdPInfo;
|
|
7475
7475
|
/** The refresh token, if applicable, to be used by the callback to request a new token from the issuer. */
|
|
7476
7476
|
refreshToken?: string;
|
|
7477
|
+
/** The token audience for GCP and Azure. */
|
|
7478
|
+
tokenAudience?: string;
|
|
7477
7479
|
}
|
|
7478
7480
|
|
|
7479
7481
|
/**
|
|
@@ -27,6 +27,9 @@ class AutomatedCallbackWorkflow extends callback_workflow_1.CallbackWorkflow {
|
|
|
27
27
|
// If the server fails for any other reason, do not clear the cache.
|
|
28
28
|
if (this.cache.hasAccessToken) {
|
|
29
29
|
const token = this.cache.getAccessToken();
|
|
30
|
+
if (!connection.accessToken) {
|
|
31
|
+
connection.accessToken = token;
|
|
32
|
+
}
|
|
30
33
|
try {
|
|
31
34
|
return await this.finishAuthentication(connection, credentials, token);
|
|
32
35
|
}
|
|
@@ -58,6 +61,9 @@ class AutomatedCallbackWorkflow extends callback_workflow_1.CallbackWorkflow {
|
|
|
58
61
|
if (credentials.username) {
|
|
59
62
|
params.username = credentials.username;
|
|
60
63
|
}
|
|
64
|
+
if (credentials.mechanismProperties.TOKEN_RESOURCE) {
|
|
65
|
+
params.tokenAudience = credentials.mechanismProperties.TOKEN_RESOURCE;
|
|
66
|
+
}
|
|
61
67
|
const timeout = timeout_1.Timeout.expires(callback_workflow_1.AUTOMATED_TIMEOUT_MS);
|
|
62
68
|
try {
|
|
63
69
|
return await Promise.race([this.executeAndValidateCallback(params), timeout]);
|
|
@@ -1 +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,CAAC;YAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;YACzE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IACE,KAAK,YAAY,kBAAU;oBAC3B,KAAK,CAAC,IAAI,KAAK,2BAAmB,CAAC,oBAAoB,EACvD,CAAC;oBACD,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;oBAC/B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;gBACrD,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;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,CAAC;YACzB,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;QACzC,CAAC;QACD,MAAM,OAAO,GAAG,iBAAO,CAAC,OAAO,CAAC,wCAAoB,CAAC,CAAC;QACtD,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,sBAAY,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnB,MAAM,IAAI,sBAAc,CAAC,iCAAiC,wCAAoB,KAAK,CAAC,CAAC;YACvF,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;CACF;
|
|
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,CAAC;YAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAC1C,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;gBAC5B,UAAU,CAAC,WAAW,GAAG,KAAK,CAAC;YACjC,CAAC;YACD,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;YACzE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IACE,KAAK,YAAY,kBAAU;oBAC3B,KAAK,CAAC,IAAI,KAAK,2BAAmB,CAAC,oBAAoB,EACvD,CAAC;oBACD,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;oBAC/B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;gBACrD,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;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,CAAC;YACzB,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;QACzC,CAAC;QACD,IAAI,WAAW,CAAC,mBAAmB,CAAC,cAAc,EAAE,CAAC;YACnD,MAAM,CAAC,aAAa,GAAG,WAAW,CAAC,mBAAmB,CAAC,cAAc,CAAC;QACxE,CAAC;QACD,MAAM,OAAO,GAAG,iBAAO,CAAC,OAAO,CAAC,wCAAoB,CAAC,CAAC;QACtD,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,sBAAY,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnB,MAAM,IAAI,sBAAc,CAAC,iCAAiC,wCAAoB,KAAK,CAAC,CAAC;YACvF,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;CACF;AAtED,8DAsEC"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.callback = void 0;
|
|
4
4
|
const azure_1 = require("../../../client-side-encryption/providers/azure");
|
|
5
5
|
const error_1 = require("../../../error");
|
|
6
6
|
const utils_1 = require("../../../utils");
|
|
7
|
-
const machine_workflow_1 = require("./machine_workflow");
|
|
8
7
|
/** Azure request headers. */
|
|
9
8
|
const AZURE_HEADERS = Object.freeze({ Metadata: 'true', Accept: 'application/json' });
|
|
10
9
|
/** Invalid endpoint result error. */
|
|
@@ -12,34 +11,23 @@ const ENDPOINT_RESULT_ERROR = 'Azure endpoint did not return a value with only a
|
|
|
12
11
|
/** Error for when the token audience is missing in the environment. */
|
|
13
12
|
const TOKEN_RESOURCE_MISSING_ERROR = 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure.';
|
|
14
13
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* @
|
|
14
|
+
* The callback function to be used in the automated callback workflow.
|
|
15
|
+
* @param params - The OIDC callback parameters.
|
|
16
|
+
* @returns The OIDC response.
|
|
18
17
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
super(cache);
|
|
18
|
+
const callback = async (params) => {
|
|
19
|
+
const tokenAudience = params.tokenAudience;
|
|
20
|
+
const username = params.username;
|
|
21
|
+
if (!tokenAudience) {
|
|
22
|
+
throw new error_1.MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
25
23
|
}
|
|
26
|
-
|
|
27
|
-
|
|
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;
|
|
24
|
+
const response = await getAzureTokenData(tokenAudience, username);
|
|
25
|
+
if (!isEndpointResultValid(response)) {
|
|
26
|
+
throw new error_1.MongoAzureError(ENDPOINT_RESULT_ERROR);
|
|
40
27
|
}
|
|
41
|
-
|
|
42
|
-
|
|
28
|
+
return response;
|
|
29
|
+
};
|
|
30
|
+
exports.callback = callback;
|
|
43
31
|
/**
|
|
44
32
|
* Hit the Azure endpoint to get the token data.
|
|
45
33
|
*/
|
|
@@ -54,8 +42,8 @@ async function getAzureTokenData(tokenAudience, username) {
|
|
|
54
42
|
}
|
|
55
43
|
const result = JSON.parse(response.body);
|
|
56
44
|
return {
|
|
57
|
-
|
|
58
|
-
|
|
45
|
+
accessToken: result.access_token,
|
|
46
|
+
expiresInSeconds: Number(result.expires_in)
|
|
59
47
|
};
|
|
60
48
|
}
|
|
61
49
|
/**
|
|
@@ -66,9 +54,9 @@ async function getAzureTokenData(tokenAudience, username) {
|
|
|
66
54
|
function isEndpointResultValid(token) {
|
|
67
55
|
if (token == null || typeof token !== 'object')
|
|
68
56
|
return false;
|
|
69
|
-
return ('
|
|
70
|
-
typeof token.
|
|
71
|
-
'
|
|
72
|
-
typeof token.
|
|
57
|
+
return ('accessToken' in token &&
|
|
58
|
+
typeof token.accessToken === 'string' &&
|
|
59
|
+
'expiresInSeconds' in token &&
|
|
60
|
+
typeof token.expiresInSeconds === 'number');
|
|
73
61
|
}
|
|
74
62
|
//# sourceMappingURL=azure_machine_workflow.js.map
|
|
@@ -1 +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;
|
|
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;AAGrC,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;AACI,MAAM,QAAQ,GAAyB,KAAK,EACjD,MAA0B,EACH,EAAE;IACzB,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjC,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,uBAAe,CAAC,4BAA4B,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAClE,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,uBAAe,CAAC,qBAAqB,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAbW,QAAA,QAAQ,YAanB;AAEF;;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,CAAC;QAC5B,MAAM,IAAI,uBAAe,CACvB,eAAe,QAAQ,CAAC,MAAM,qDAAqD,QAAQ,CAAC,IAAI,EAAE,CACnG,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO;QACL,WAAW,EAAE,MAAM,CAAC,YAAY;QAChC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;KAC5C,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,aAAa,IAAI,KAAK;QACtB,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ;QACrC,kBAAkB,IAAI,KAAK;QAC3B,OAAO,KAAK,CAAC,gBAAgB,KAAK,QAAQ,CAC3C,CAAC;AACJ,CAAC"}
|
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.callback = void 0;
|
|
4
4
|
const error_1 = require("../../../error");
|
|
5
5
|
const utils_1 = require("../../../utils");
|
|
6
|
-
const machine_workflow_1 = require("./machine_workflow");
|
|
7
6
|
/** GCP base URL. */
|
|
8
7
|
const GCP_BASE_URL = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity';
|
|
9
8
|
/** GCP request headers. */
|
|
10
9
|
const GCP_HEADERS = Object.freeze({ 'Metadata-Flavor': 'Google' });
|
|
11
10
|
/** Error for when the token audience is missing in the environment. */
|
|
12
11
|
const TOKEN_RESOURCE_MISSING_ERROR = 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is gcp.';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*/
|
|
23
|
-
async getToken(credentials) {
|
|
24
|
-
const tokenAudience = credentials?.mechanismProperties.TOKEN_RESOURCE;
|
|
25
|
-
if (!tokenAudience) {
|
|
26
|
-
throw new error_1.MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
27
|
-
}
|
|
28
|
-
return await getGcpTokenData(tokenAudience);
|
|
12
|
+
/**
|
|
13
|
+
* The callback function to be used in the automated callback workflow.
|
|
14
|
+
* @param params - The OIDC callback parameters.
|
|
15
|
+
* @returns The OIDC response.
|
|
16
|
+
*/
|
|
17
|
+
const callback = async (params) => {
|
|
18
|
+
const tokenAudience = params.tokenAudience;
|
|
19
|
+
if (!tokenAudience) {
|
|
20
|
+
throw new error_1.MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
29
21
|
}
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
return await getGcpTokenData(tokenAudience);
|
|
23
|
+
};
|
|
24
|
+
exports.callback = callback;
|
|
32
25
|
/**
|
|
33
26
|
* Hit the GCP endpoint to get the token data.
|
|
34
27
|
*/
|
|
@@ -41,6 +34,6 @@ async function getGcpTokenData(tokenAudience) {
|
|
|
41
34
|
if (response.status !== 200) {
|
|
42
35
|
throw new error_1.MongoGCPError(`Status code ${response.status} returned from the GCP endpoint. Response body: ${response.body}`);
|
|
43
36
|
}
|
|
44
|
-
return {
|
|
37
|
+
return { accessToken: response.body };
|
|
45
38
|
}
|
|
46
39
|
//# sourceMappingURL=gcp_machine_workflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcp_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,0CAA+C;AAC/C,0CAAqC;
|
|
1
|
+
{"version":3,"file":"gcp_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,0CAA+C;AAC/C,0CAAqC;AAGrC,oBAAoB;AACpB,MAAM,YAAY,GAChB,+EAA+E,CAAC;AAElF,2BAA2B;AAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC;AAEnE,uEAAuE;AACvE,MAAM,4BAA4B,GAChC,sFAAsF,CAAC;AAEzF;;;;GAIG;AACI,MAAM,QAAQ,GAAyB,KAAK,EACjD,MAA0B,EACH,EAAE;IACzB,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,qBAAa,CAAC,4BAA4B,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;AAC9C,CAAC,CAAC;AARW,QAAA,QAAQ,YAQnB;AAEF;;GAEG;AACH,KAAK,UAAU,eAAe,CAAC,aAAqB;IAClD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAClC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,IAAA,WAAG,EAAC,GAAG,EAAE;QAC9B,OAAO,EAAE,WAAW;KACrB,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,IAAI,qBAAa,CACrB,eAAe,QAAQ,CAAC,MAAM,mDAAmD,QAAQ,CAAC,IAAI,EAAE,CACjG,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -1,38 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.callback = void 0;
|
|
4
4
|
const promises_1 = require("fs/promises");
|
|
5
|
-
const machine_workflow_1 = require("./machine_workflow");
|
|
6
5
|
/** The fallback file name */
|
|
7
6
|
const FALLBACK_FILENAME = '/var/run/secrets/kubernetes.io/serviceaccount/token';
|
|
8
7
|
/** The azure environment variable for the file name. */
|
|
9
8
|
const AZURE_FILENAME = 'AZURE_FEDERATED_TOKEN_FILE';
|
|
10
9
|
/** The AWS environment variable for the file name. */
|
|
11
10
|
const AWS_FILENAME = 'AWS_WEB_IDENTITY_TOKEN_FILE';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
/**
|
|
12
|
+
* The callback function to be used in the automated callback workflow.
|
|
13
|
+
* @param params - The OIDC callback parameters.
|
|
14
|
+
* @returns The OIDC response.
|
|
15
|
+
*/
|
|
16
|
+
const callback = async () => {
|
|
17
|
+
let filename;
|
|
18
|
+
if (process.env[AZURE_FILENAME]) {
|
|
19
|
+
filename = process.env[AZURE_FILENAME];
|
|
18
20
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
async getToken() {
|
|
23
|
-
let filename;
|
|
24
|
-
if (process.env[AZURE_FILENAME]) {
|
|
25
|
-
filename = process.env[AZURE_FILENAME];
|
|
26
|
-
}
|
|
27
|
-
else if (process.env[AWS_FILENAME]) {
|
|
28
|
-
filename = process.env[AWS_FILENAME];
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
filename = FALLBACK_FILENAME;
|
|
32
|
-
}
|
|
33
|
-
const token = await (0, promises_1.readFile)(filename, 'utf8');
|
|
34
|
-
return { access_token: token };
|
|
21
|
+
else if (process.env[AWS_FILENAME]) {
|
|
22
|
+
filename = process.env[AWS_FILENAME];
|
|
35
23
|
}
|
|
36
|
-
|
|
37
|
-
|
|
24
|
+
else {
|
|
25
|
+
filename = FALLBACK_FILENAME;
|
|
26
|
+
}
|
|
27
|
+
const token = await (0, promises_1.readFile)(filename, 'utf8');
|
|
28
|
+
return { accessToken: token };
|
|
29
|
+
};
|
|
30
|
+
exports.callback = callback;
|
|
38
31
|
//# sourceMappingURL=k8s_machine_workflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k8s_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,0CAAuC;
|
|
1
|
+
{"version":3,"file":"k8s_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,0CAAuC;AAIvC,6BAA6B;AAC7B,MAAM,iBAAiB,GAAG,qDAAqD,CAAC;AAEhF,wDAAwD;AACxD,MAAM,cAAc,GAAG,4BAA4B,CAAC;AAEpD,sDAAsD;AACtD,MAAM,YAAY,GAAG,6BAA6B,CAAC;AAEnD;;;;GAIG;AACI,MAAM,QAAQ,GAAyB,KAAK,IAA2B,EAAE;IAC9E,IAAI,QAAgB,CAAC;IACrB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;SAAM,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QACrC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,iBAAiB,CAAC;IAC/B,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/C,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC,CAAC;AAXW,QAAA,QAAQ,YAWnB"}
|
|
@@ -1,34 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.callback = void 0;
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const error_1 = require("../../../error");
|
|
6
|
-
const machine_workflow_1 = require("./machine_workflow");
|
|
7
6
|
/** Error for when the token is missing in the environment. */
|
|
8
7
|
const TOKEN_MISSING_ERROR = 'OIDC_TOKEN_FILE must be set in the environment.';
|
|
9
8
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* @
|
|
9
|
+
* The callback function to be used in the automated callback workflow.
|
|
10
|
+
* @param params - The OIDC callback parameters.
|
|
11
|
+
* @returns The OIDC response.
|
|
13
12
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
constructor(cache) {
|
|
19
|
-
super(cache);
|
|
13
|
+
const callback = async () => {
|
|
14
|
+
const tokenFile = process.env.OIDC_TOKEN_FILE;
|
|
15
|
+
if (!tokenFile) {
|
|
16
|
+
throw new error_1.MongoAWSError(TOKEN_MISSING_ERROR);
|
|
20
17
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const tokenFile = process.env.OIDC_TOKEN_FILE;
|
|
26
|
-
if (!tokenFile) {
|
|
27
|
-
throw new error_1.MongoAWSError(TOKEN_MISSING_ERROR);
|
|
28
|
-
}
|
|
29
|
-
const token = await fs.promises.readFile(tokenFile, 'utf8');
|
|
30
|
-
return { access_token: token };
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
exports.TokenMachineWorkflow = TokenMachineWorkflow;
|
|
18
|
+
const token = await fs.promises.readFile(tokenFile, 'utf8');
|
|
19
|
+
return { accessToken: token };
|
|
20
|
+
};
|
|
21
|
+
exports.callback = callback;
|
|
34
22
|
//# sourceMappingURL=token_machine_workflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/token_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AAEzB,0CAA+C;
|
|
1
|
+
{"version":3,"file":"token_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/token_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AAEzB,0CAA+C;AAG/C,8DAA8D;AAC9D,MAAM,mBAAmB,GAAG,iDAAiD,CAAC;AAE9E;;;;GAIG;AACI,MAAM,QAAQ,GAAyB,KAAK,IAA2B,EAAE;IAC9E,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC9C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,qBAAa,CAAC,mBAAmB,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5D,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC,CAAC;AAPW,QAAA,QAAQ,YAOnB"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MongoDBOIDC = exports.OIDC_WORKFLOWS = exports.OIDC_VERSION = void 0;
|
|
4
4
|
const error_1 = require("../../error");
|
|
5
5
|
const auth_provider_1 = require("./auth_provider");
|
|
6
|
+
const automated_callback_workflow_1 = require("./mongodb_oidc/automated_callback_workflow");
|
|
6
7
|
const azure_machine_workflow_1 = require("./mongodb_oidc/azure_machine_workflow");
|
|
7
8
|
const gcp_machine_workflow_1 = require("./mongodb_oidc/gcp_machine_workflow");
|
|
8
9
|
const k8s_machine_workflow_1 = require("./mongodb_oidc/k8s_machine_workflow");
|
|
@@ -14,10 +15,10 @@ const MISSING_CREDENTIALS_ERROR = 'AuthContext must provide credentials.';
|
|
|
14
15
|
exports.OIDC_VERSION = 1;
|
|
15
16
|
/** @internal */
|
|
16
17
|
exports.OIDC_WORKFLOWS = new Map();
|
|
17
|
-
exports.OIDC_WORKFLOWS.set('test', () => new
|
|
18
|
-
exports.OIDC_WORKFLOWS.set('azure', () => new
|
|
19
|
-
exports.OIDC_WORKFLOWS.set('gcp', () => new
|
|
20
|
-
exports.OIDC_WORKFLOWS.set('k8s', () => new
|
|
18
|
+
exports.OIDC_WORKFLOWS.set('test', () => new automated_callback_workflow_1.AutomatedCallbackWorkflow(new token_cache_1.TokenCache(), token_machine_workflow_1.callback));
|
|
19
|
+
exports.OIDC_WORKFLOWS.set('azure', () => new automated_callback_workflow_1.AutomatedCallbackWorkflow(new token_cache_1.TokenCache(), azure_machine_workflow_1.callback));
|
|
20
|
+
exports.OIDC_WORKFLOWS.set('gcp', () => new automated_callback_workflow_1.AutomatedCallbackWorkflow(new token_cache_1.TokenCache(), gcp_machine_workflow_1.callback));
|
|
21
|
+
exports.OIDC_WORKFLOWS.set('k8s', () => new automated_callback_workflow_1.AutomatedCallbackWorkflow(new token_cache_1.TokenCache(), k8s_machine_workflow_1.callback));
|
|
21
22
|
/**
|
|
22
23
|
* OIDC auth provider.
|
|
23
24
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongodb_oidc.js","sourceRoot":"","sources":["../../../src/cmap/auth/mongodb_oidc.ts"],"names":[],"mappings":";;;AACA,uCAAsF;AAGtF,mDAAiE;AAEjE,
|
|
1
|
+
{"version":3,"file":"mongodb_oidc.js","sourceRoot":"","sources":["../../../src/cmap/auth/mongodb_oidc.ts"],"names":[],"mappings":";;;AACA,uCAAsF;AAGtF,mDAAiE;AAEjE,4FAAuF;AACvF,kFAAkF;AAClF,8EAA8E;AAC9E,8EAA8E;AAC9E,4DAAwD;AACxD,kFAAiF;AAEjF,0CAA0C;AAC1C,MAAM,yBAAyB,GAAG,uCAAuC,CAAC;AA6E1E,kDAAkD;AACrC,QAAA,YAAY,GAAG,CAAC,CAAC;AA6B9B,gBAAgB;AACH,QAAA,cAAc,GAAyC,IAAI,GAAG,EAAE,CAAC;AAC9E,sBAAc,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,uDAAyB,CAAC,IAAI,wBAAU,EAAE,EAAE,iCAAY,CAAC,CAAC,CAAC;AAChG,sBAAc,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,uDAAyB,CAAC,IAAI,wBAAU,EAAE,EAAE,iCAAa,CAAC,CAAC,CAAC;AAClG,sBAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,uDAAyB,CAAC,IAAI,wBAAU,EAAE,EAAE,+BAAW,CAAC,CAAC,CAAC;AAC9F,sBAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,uDAAyB,CAAC,IAAI,wBAAU,EAAE,EAAE,+BAAW,CAAC,CAAC,CAAC;AAE9F;;GAEG;AACH,MAAa,WAAY,SAAQ,4BAAY;IAG3C;;OAEG;IACH,YAAY,QAAmB;QAC7B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,iCAAyB,CAAC,iDAAiD,CAAC,CAAC;QACzF,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;OAEG;IACM,KAAK,CAAC,IAAI,CAAC,WAAwB;QAC1C,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC;QAC/D,IAAI,QAAQ,EAAE,uBAAuB,EAAE,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACjE,OAAO;QACT,CAAC;QACD,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,gBAAgB,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED;;OAEG;IACM,KAAK,CAAC,OAAO,CACpB,YAA+B,EAC/B,WAAwB;QAExB,MAAM,EAAE,UAAU,EAAE,GAAG,WAAW,CAAC;QACnC,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC5E,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,MAAM,EAAE,CAAC;IACxC,CAAC;CACF;AA1CD,kCA0CC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,WAAwB;IAC9C,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC;IACpC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,oCAA4B,CAAC,yBAAyB,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
|
package/mongodb.d.ts
CHANGED
|
@@ -7427,6 +7427,8 @@ export declare interface OIDCCallbackParams {
|
|
|
7427
7427
|
idpInfo?: IdPInfo;
|
|
7428
7428
|
/** The refresh token, if applicable, to be used by the callback to request a new token from the issuer. */
|
|
7429
7429
|
refreshToken?: string;
|
|
7430
|
+
/** The token audience for GCP and Azure. */
|
|
7431
|
+
tokenAudience?: string;
|
|
7430
7432
|
}
|
|
7431
7433
|
|
|
7432
7434
|
/**
|
package/package.json
CHANGED
|
@@ -34,6 +34,9 @@ export class AutomatedCallbackWorkflow extends CallbackWorkflow {
|
|
|
34
34
|
// If the server fails for any other reason, do not clear the cache.
|
|
35
35
|
if (this.cache.hasAccessToken) {
|
|
36
36
|
const token = this.cache.getAccessToken();
|
|
37
|
+
if (!connection.accessToken) {
|
|
38
|
+
connection.accessToken = token;
|
|
39
|
+
}
|
|
37
40
|
try {
|
|
38
41
|
return await this.finishAuthentication(connection, credentials, token);
|
|
39
42
|
} catch (error) {
|
|
@@ -66,6 +69,9 @@ export class AutomatedCallbackWorkflow extends CallbackWorkflow {
|
|
|
66
69
|
if (credentials.username) {
|
|
67
70
|
params.username = credentials.username;
|
|
68
71
|
}
|
|
72
|
+
if (credentials.mechanismProperties.TOKEN_RESOURCE) {
|
|
73
|
+
params.tokenAudience = credentials.mechanismProperties.TOKEN_RESOURCE;
|
|
74
|
+
}
|
|
69
75
|
const timeout = Timeout.expires(AUTOMATED_TIMEOUT_MS);
|
|
70
76
|
try {
|
|
71
77
|
return await Promise.race([this.executeAndValidateCallback(params), timeout]);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { addAzureParams, AZURE_BASE_URL } from '../../../client-side-encryption/providers/azure';
|
|
2
2
|
import { MongoAzureError } from '../../../error';
|
|
3
3
|
import { get } from '../../../utils';
|
|
4
|
-
import type {
|
|
5
|
-
import { type AccessToken, MachineWorkflow } from './machine_workflow';
|
|
6
|
-
import { type TokenCache } from './token_cache';
|
|
4
|
+
import type { OIDCCallbackFunction, OIDCCallbackParams, OIDCResponse } from '../mongodb_oidc';
|
|
7
5
|
|
|
8
6
|
/** Azure request headers. */
|
|
9
7
|
const AZURE_HEADERS = Object.freeze({ Metadata: 'true', Accept: 'application/json' });
|
|
@@ -17,39 +15,29 @@ const TOKEN_RESOURCE_MISSING_ERROR =
|
|
|
17
15
|
'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure.';
|
|
18
16
|
|
|
19
17
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* @
|
|
18
|
+
* The callback function to be used in the automated callback workflow.
|
|
19
|
+
* @param params - The OIDC callback parameters.
|
|
20
|
+
* @returns The OIDC response.
|
|
23
21
|
*/
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
export const callback: OIDCCallbackFunction = async (
|
|
23
|
+
params: OIDCCallbackParams
|
|
24
|
+
): Promise<OIDCResponse> => {
|
|
25
|
+
const tokenAudience = params.tokenAudience;
|
|
26
|
+
const username = params.username;
|
|
27
|
+
if (!tokenAudience) {
|
|
28
|
+
throw new MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*/
|
|
35
|
-
async getToken(credentials?: MongoCredentials): Promise<AccessToken> {
|
|
36
|
-
const tokenAudience = credentials?.mechanismProperties.TOKEN_RESOURCE;
|
|
37
|
-
const username = credentials?.username;
|
|
38
|
-
if (!tokenAudience) {
|
|
39
|
-
throw new MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
40
|
-
}
|
|
41
|
-
const response = await getAzureTokenData(tokenAudience, username);
|
|
42
|
-
if (!isEndpointResultValid(response)) {
|
|
43
|
-
throw new MongoAzureError(ENDPOINT_RESULT_ERROR);
|
|
44
|
-
}
|
|
45
|
-
return response;
|
|
30
|
+
const response = await getAzureTokenData(tokenAudience, username);
|
|
31
|
+
if (!isEndpointResultValid(response)) {
|
|
32
|
+
throw new MongoAzureError(ENDPOINT_RESULT_ERROR);
|
|
46
33
|
}
|
|
47
|
-
|
|
34
|
+
return response;
|
|
35
|
+
};
|
|
48
36
|
|
|
49
37
|
/**
|
|
50
38
|
* Hit the Azure endpoint to get the token data.
|
|
51
39
|
*/
|
|
52
|
-
async function getAzureTokenData(tokenAudience: string, username?: string): Promise<
|
|
40
|
+
async function getAzureTokenData(tokenAudience: string, username?: string): Promise<OIDCResponse> {
|
|
53
41
|
const url = new URL(AZURE_BASE_URL);
|
|
54
42
|
addAzureParams(url, tokenAudience, username);
|
|
55
43
|
const response = await get(url, {
|
|
@@ -62,8 +50,8 @@ async function getAzureTokenData(tokenAudience: string, username?: string): Prom
|
|
|
62
50
|
}
|
|
63
51
|
const result = JSON.parse(response.body);
|
|
64
52
|
return {
|
|
65
|
-
|
|
66
|
-
|
|
53
|
+
accessToken: result.access_token,
|
|
54
|
+
expiresInSeconds: Number(result.expires_in)
|
|
67
55
|
};
|
|
68
56
|
}
|
|
69
57
|
|
|
@@ -77,9 +65,9 @@ function isEndpointResultValid(
|
|
|
77
65
|
): token is { access_token: unknown; expires_in: unknown } {
|
|
78
66
|
if (token == null || typeof token !== 'object') return false;
|
|
79
67
|
return (
|
|
80
|
-
'
|
|
81
|
-
typeof token.
|
|
82
|
-
'
|
|
83
|
-
typeof token.
|
|
68
|
+
'accessToken' in token &&
|
|
69
|
+
typeof token.accessToken === 'string' &&
|
|
70
|
+
'expiresInSeconds' in token &&
|
|
71
|
+
typeof token.expiresInSeconds === 'number'
|
|
84
72
|
);
|
|
85
73
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { MongoGCPError } from '../../../error';
|
|
2
2
|
import { get } from '../../../utils';
|
|
3
|
-
import {
|
|
4
|
-
import { type AccessToken, MachineWorkflow } from './machine_workflow';
|
|
5
|
-
import { type TokenCache } from './token_cache';
|
|
3
|
+
import type { OIDCCallbackFunction, OIDCCallbackParams, OIDCResponse } from '../mongodb_oidc';
|
|
6
4
|
|
|
7
5
|
/** GCP base URL. */
|
|
8
6
|
const GCP_BASE_URL =
|
|
@@ -15,30 +13,25 @@ const GCP_HEADERS = Object.freeze({ 'Metadata-Flavor': 'Google' });
|
|
|
15
13
|
const TOKEN_RESOURCE_MISSING_ERROR =
|
|
16
14
|
'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is gcp.';
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
async getToken(credentials?: MongoCredentials): Promise<AccessToken> {
|
|
30
|
-
const tokenAudience = credentials?.mechanismProperties.TOKEN_RESOURCE;
|
|
31
|
-
if (!tokenAudience) {
|
|
32
|
-
throw new MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
33
|
-
}
|
|
34
|
-
return await getGcpTokenData(tokenAudience);
|
|
16
|
+
/**
|
|
17
|
+
* The callback function to be used in the automated callback workflow.
|
|
18
|
+
* @param params - The OIDC callback parameters.
|
|
19
|
+
* @returns The OIDC response.
|
|
20
|
+
*/
|
|
21
|
+
export const callback: OIDCCallbackFunction = async (
|
|
22
|
+
params: OIDCCallbackParams
|
|
23
|
+
): Promise<OIDCResponse> => {
|
|
24
|
+
const tokenAudience = params.tokenAudience;
|
|
25
|
+
if (!tokenAudience) {
|
|
26
|
+
throw new MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
|
|
35
27
|
}
|
|
36
|
-
|
|
28
|
+
return await getGcpTokenData(tokenAudience);
|
|
29
|
+
};
|
|
37
30
|
|
|
38
31
|
/**
|
|
39
32
|
* Hit the GCP endpoint to get the token data.
|
|
40
33
|
*/
|
|
41
|
-
async function getGcpTokenData(tokenAudience: string): Promise<
|
|
34
|
+
async function getGcpTokenData(tokenAudience: string): Promise<OIDCResponse> {
|
|
42
35
|
const url = new URL(GCP_BASE_URL);
|
|
43
36
|
url.searchParams.append('audience', tokenAudience);
|
|
44
37
|
const response = await get(url, {
|
|
@@ -49,5 +42,5 @@ async function getGcpTokenData(tokenAudience: string): Promise<AccessToken> {
|
|
|
49
42
|
`Status code ${response.status} returned from the GCP endpoint. Response body: ${response.body}`
|
|
50
43
|
);
|
|
51
44
|
}
|
|
52
|
-
return {
|
|
45
|
+
return { accessToken: response.body };
|
|
53
46
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'fs/promises';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { type TokenCache } from './token_cache';
|
|
3
|
+
import type { OIDCCallbackFunction, OIDCResponse } from '../mongodb_oidc';
|
|
5
4
|
|
|
6
5
|
/** The fallback file name */
|
|
7
6
|
const FALLBACK_FILENAME = '/var/run/secrets/kubernetes.io/serviceaccount/token';
|
|
@@ -12,27 +11,20 @@ const AZURE_FILENAME = 'AZURE_FEDERATED_TOKEN_FILE';
|
|
|
12
11
|
/** The AWS environment variable for the file name. */
|
|
13
12
|
const AWS_FILENAME = 'AWS_WEB_IDENTITY_TOKEN_FILE';
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The callback function to be used in the automated callback workflow.
|
|
16
|
+
* @param params - The OIDC callback parameters.
|
|
17
|
+
* @returns The OIDC response.
|
|
18
|
+
*/
|
|
19
|
+
export const callback: OIDCCallbackFunction = async (): Promise<OIDCResponse> => {
|
|
20
|
+
let filename: string;
|
|
21
|
+
if (process.env[AZURE_FILENAME]) {
|
|
22
|
+
filename = process.env[AZURE_FILENAME];
|
|
23
|
+
} else if (process.env[AWS_FILENAME]) {
|
|
24
|
+
filename = process.env[AWS_FILENAME];
|
|
25
|
+
} else {
|
|
26
|
+
filename = FALLBACK_FILENAME;
|
|
21
27
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*/
|
|
26
|
-
async getToken(): Promise<AccessToken> {
|
|
27
|
-
let filename: string;
|
|
28
|
-
if (process.env[AZURE_FILENAME]) {
|
|
29
|
-
filename = process.env[AZURE_FILENAME];
|
|
30
|
-
} else if (process.env[AWS_FILENAME]) {
|
|
31
|
-
filename = process.env[AWS_FILENAME];
|
|
32
|
-
} else {
|
|
33
|
-
filename = FALLBACK_FILENAME;
|
|
34
|
-
}
|
|
35
|
-
const token = await readFile(filename, 'utf8');
|
|
36
|
-
return { access_token: token };
|
|
37
|
-
}
|
|
38
|
-
}
|
|
28
|
+
const token = await readFile(filename, 'utf8');
|
|
29
|
+
return { accessToken: token };
|
|
30
|
+
};
|
|
@@ -1,34 +1,21 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
|
|
3
3
|
import { MongoAWSError } from '../../../error';
|
|
4
|
-
import {
|
|
5
|
-
import { type TokenCache } from './token_cache';
|
|
4
|
+
import type { OIDCCallbackFunction, OIDCResponse } from '../mongodb_oidc';
|
|
6
5
|
|
|
7
6
|
/** Error for when the token is missing in the environment. */
|
|
8
7
|
const TOKEN_MISSING_ERROR = 'OIDC_TOKEN_FILE must be set in the environment.';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @
|
|
10
|
+
* The callback function to be used in the automated callback workflow.
|
|
11
|
+
* @param params - The OIDC callback parameters.
|
|
12
|
+
* @returns The OIDC response.
|
|
14
13
|
*/
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
constructor(cache: TokenCache) {
|
|
20
|
-
super(cache);
|
|
14
|
+
export const callback: OIDCCallbackFunction = async (): Promise<OIDCResponse> => {
|
|
15
|
+
const tokenFile = process.env.OIDC_TOKEN_FILE;
|
|
16
|
+
if (!tokenFile) {
|
|
17
|
+
throw new MongoAWSError(TOKEN_MISSING_ERROR);
|
|
21
18
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*/
|
|
26
|
-
async getToken(): Promise<AccessToken> {
|
|
27
|
-
const tokenFile = process.env.OIDC_TOKEN_FILE;
|
|
28
|
-
if (!tokenFile) {
|
|
29
|
-
throw new MongoAWSError(TOKEN_MISSING_ERROR);
|
|
30
|
-
}
|
|
31
|
-
const token = await fs.promises.readFile(tokenFile, 'utf8');
|
|
32
|
-
return { access_token: token };
|
|
33
|
-
}
|
|
34
|
-
}
|
|
19
|
+
const token = await fs.promises.readFile(tokenFile, 'utf8');
|
|
20
|
+
return { accessToken: token };
|
|
21
|
+
};
|
|
@@ -4,11 +4,12 @@ import type { HandshakeDocument } from '../connect';
|
|
|
4
4
|
import type { Connection } from '../connection';
|
|
5
5
|
import { type AuthContext, AuthProvider } from './auth_provider';
|
|
6
6
|
import type { MongoCredentials } from './mongo_credentials';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { AutomatedCallbackWorkflow } from './mongodb_oidc/automated_callback_workflow';
|
|
8
|
+
import { callback as azureCallback } from './mongodb_oidc/azure_machine_workflow';
|
|
9
|
+
import { callback as gcpCallback } from './mongodb_oidc/gcp_machine_workflow';
|
|
10
|
+
import { callback as k8sCallback } from './mongodb_oidc/k8s_machine_workflow';
|
|
10
11
|
import { TokenCache } from './mongodb_oidc/token_cache';
|
|
11
|
-
import {
|
|
12
|
+
import { callback as testCallback } from './mongodb_oidc/token_machine_workflow';
|
|
12
13
|
|
|
13
14
|
/** Error when credentials are missing. */
|
|
14
15
|
const MISSING_CREDENTIALS_ERROR = 'AuthContext must provide credentials.';
|
|
@@ -78,6 +79,8 @@ export interface OIDCCallbackParams {
|
|
|
78
79
|
idpInfo?: IdPInfo;
|
|
79
80
|
/** The refresh token, if applicable, to be used by the callback to request a new token from the issuer. */
|
|
80
81
|
refreshToken?: string;
|
|
82
|
+
/** The token audience for GCP and Azure. */
|
|
83
|
+
tokenAudience?: string;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
/**
|
|
@@ -93,6 +96,8 @@ type EnvironmentName = 'test' | 'azure' | 'gcp' | 'k8s' | undefined;
|
|
|
93
96
|
|
|
94
97
|
/** @internal */
|
|
95
98
|
export interface Workflow {
|
|
99
|
+
cache: TokenCache;
|
|
100
|
+
|
|
96
101
|
/**
|
|
97
102
|
* All device workflows must implement this method in order to get the access
|
|
98
103
|
* token and then call authenticate with it.
|
|
@@ -116,10 +121,10 @@ export interface Workflow {
|
|
|
116
121
|
|
|
117
122
|
/** @internal */
|
|
118
123
|
export const OIDC_WORKFLOWS: Map<EnvironmentName, () => Workflow> = new Map();
|
|
119
|
-
OIDC_WORKFLOWS.set('test', () => new
|
|
120
|
-
OIDC_WORKFLOWS.set('azure', () => new
|
|
121
|
-
OIDC_WORKFLOWS.set('gcp', () => new
|
|
122
|
-
OIDC_WORKFLOWS.set('k8s', () => new
|
|
124
|
+
OIDC_WORKFLOWS.set('test', () => new AutomatedCallbackWorkflow(new TokenCache(), testCallback));
|
|
125
|
+
OIDC_WORKFLOWS.set('azure', () => new AutomatedCallbackWorkflow(new TokenCache(), azureCallback));
|
|
126
|
+
OIDC_WORKFLOWS.set('gcp', () => new AutomatedCallbackWorkflow(new TokenCache(), gcpCallback));
|
|
127
|
+
OIDC_WORKFLOWS.set('k8s', () => new AutomatedCallbackWorkflow(new TokenCache(), k8sCallback));
|
|
123
128
|
|
|
124
129
|
/**
|
|
125
130
|
* OIDC auth provider.
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MachineWorkflow = void 0;
|
|
4
|
-
const promises_1 = require("timers/promises");
|
|
5
|
-
const utils_1 = require("../../../utils");
|
|
6
|
-
const command_builders_1 = require("./command_builders");
|
|
7
|
-
/** The time to throttle callback calls. */
|
|
8
|
-
const THROTTLE_MS = 100;
|
|
9
|
-
/**
|
|
10
|
-
* Common behaviour for OIDC machine workflows.
|
|
11
|
-
* @internal
|
|
12
|
-
*/
|
|
13
|
-
class MachineWorkflow {
|
|
14
|
-
/**
|
|
15
|
-
* Instantiate the machine workflow.
|
|
16
|
-
*/
|
|
17
|
-
constructor(cache) {
|
|
18
|
-
this.cache = cache;
|
|
19
|
-
this.callback = this.withLock(this.getToken.bind(this));
|
|
20
|
-
this.lastExecutionTime = Date.now() - THROTTLE_MS;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Execute the workflow. Gets the token from the subclass implementation.
|
|
24
|
-
*/
|
|
25
|
-
async execute(connection, credentials) {
|
|
26
|
-
const token = await this.getTokenFromCacheOrEnv(connection, credentials);
|
|
27
|
-
const command = (0, command_builders_1.finishCommandDocument)(token);
|
|
28
|
-
await connection.command((0, utils_1.ns)(credentials.source), command, undefined);
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Reauthenticate on a machine workflow just grabs the token again since the server
|
|
32
|
-
* has said the current access token is invalid or expired.
|
|
33
|
-
*/
|
|
34
|
-
async reauthenticate(connection, credentials) {
|
|
35
|
-
if (this.cache.hasAccessToken) {
|
|
36
|
-
// Reauthentication implies the token has expired.
|
|
37
|
-
if (connection.accessToken === this.cache.getAccessToken()) {
|
|
38
|
-
// If connection's access token is the same as the cache's, remove
|
|
39
|
-
// the token from the cache and connection.
|
|
40
|
-
this.cache.removeAccessToken();
|
|
41
|
-
delete connection.accessToken;
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// If the connection's access token is different from the cache's, set
|
|
45
|
-
// the cache's token on the connection and do not remove from the
|
|
46
|
-
// cache.
|
|
47
|
-
connection.accessToken = this.cache.getAccessToken();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
await this.execute(connection, credentials);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Get the document to add for speculative authentication.
|
|
54
|
-
*/
|
|
55
|
-
async speculativeAuth(connection, credentials) {
|
|
56
|
-
// The spec states only cached access tokens can use speculative auth.
|
|
57
|
-
if (!this.cache.hasAccessToken) {
|
|
58
|
-
return {};
|
|
59
|
-
}
|
|
60
|
-
const token = await this.getTokenFromCacheOrEnv(connection, credentials);
|
|
61
|
-
const document = (0, command_builders_1.finishCommandDocument)(token);
|
|
62
|
-
document.db = credentials.source;
|
|
63
|
-
return { speculativeAuthenticate: document };
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Get the token from the cache or environment.
|
|
67
|
-
*/
|
|
68
|
-
async getTokenFromCacheOrEnv(connection, credentials) {
|
|
69
|
-
if (this.cache.hasAccessToken) {
|
|
70
|
-
const token = this.cache.getAccessToken();
|
|
71
|
-
// New connections won't have an access token so ensure we set here.
|
|
72
|
-
if (!connection.accessToken) {
|
|
73
|
-
connection.accessToken = token;
|
|
74
|
-
}
|
|
75
|
-
return token;
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
const token = await this.callback(credentials);
|
|
79
|
-
this.cache.put({ accessToken: token.access_token, expiresInSeconds: token.expires_in });
|
|
80
|
-
// Put the access token on the connection as well.
|
|
81
|
-
connection.accessToken = token.access_token;
|
|
82
|
-
return token.access_token;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Ensure the callback is only executed one at a time, and throttled to
|
|
87
|
-
* only once per 100ms.
|
|
88
|
-
*/
|
|
89
|
-
withLock(callback) {
|
|
90
|
-
let lock = Promise.resolve();
|
|
91
|
-
return async (credentials) => {
|
|
92
|
-
// We do this to ensure that we would never return the result of the
|
|
93
|
-
// previous lock, only the current callback's value would get returned.
|
|
94
|
-
await lock;
|
|
95
|
-
lock = lock
|
|
96
|
-
.catch(() => null)
|
|
97
|
-
.then(async () => {
|
|
98
|
-
const difference = Date.now() - this.lastExecutionTime;
|
|
99
|
-
if (difference <= THROTTLE_MS) {
|
|
100
|
-
await (0, promises_1.setTimeout)(THROTTLE_MS - difference);
|
|
101
|
-
}
|
|
102
|
-
this.lastExecutionTime = Date.now();
|
|
103
|
-
return await callback(credentials);
|
|
104
|
-
});
|
|
105
|
-
return await lock;
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
exports.MachineWorkflow = MachineWorkflow;
|
|
110
|
-
//# sourceMappingURL=machine_workflow.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/machine_workflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { setTimeout } from 'timers/promises';
|
|
2
|
-
|
|
3
|
-
import { type Document } from '../../../bson';
|
|
4
|
-
import { ns } from '../../../utils';
|
|
5
|
-
import type { Connection } from '../../connection';
|
|
6
|
-
import type { MongoCredentials } from '../mongo_credentials';
|
|
7
|
-
import type { Workflow } from '../mongodb_oidc';
|
|
8
|
-
import { finishCommandDocument } from './command_builders';
|
|
9
|
-
import { type TokenCache } from './token_cache';
|
|
10
|
-
|
|
11
|
-
/** The time to throttle callback calls. */
|
|
12
|
-
const THROTTLE_MS = 100;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* The access token format.
|
|
16
|
-
* @internal
|
|
17
|
-
*/
|
|
18
|
-
export interface AccessToken {
|
|
19
|
-
access_token: string;
|
|
20
|
-
expires_in?: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** @internal */
|
|
24
|
-
export type OIDCTokenFunction = (credentials: MongoCredentials) => Promise<AccessToken>;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Common behaviour for OIDC machine workflows.
|
|
28
|
-
* @internal
|
|
29
|
-
*/
|
|
30
|
-
export abstract class MachineWorkflow implements Workflow {
|
|
31
|
-
cache: TokenCache;
|
|
32
|
-
callback: OIDCTokenFunction;
|
|
33
|
-
lastExecutionTime: number;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Instantiate the machine workflow.
|
|
37
|
-
*/
|
|
38
|
-
constructor(cache: TokenCache) {
|
|
39
|
-
this.cache = cache;
|
|
40
|
-
this.callback = this.withLock(this.getToken.bind(this));
|
|
41
|
-
this.lastExecutionTime = Date.now() - THROTTLE_MS;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Execute the workflow. Gets the token from the subclass implementation.
|
|
46
|
-
*/
|
|
47
|
-
async execute(connection: Connection, credentials: MongoCredentials): Promise<void> {
|
|
48
|
-
const token = await this.getTokenFromCacheOrEnv(connection, credentials);
|
|
49
|
-
const command = finishCommandDocument(token);
|
|
50
|
-
await connection.command(ns(credentials.source), command, undefined);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Reauthenticate on a machine workflow just grabs the token again since the server
|
|
55
|
-
* has said the current access token is invalid or expired.
|
|
56
|
-
*/
|
|
57
|
-
async reauthenticate(connection: Connection, credentials: MongoCredentials): Promise<void> {
|
|
58
|
-
if (this.cache.hasAccessToken) {
|
|
59
|
-
// Reauthentication implies the token has expired.
|
|
60
|
-
if (connection.accessToken === this.cache.getAccessToken()) {
|
|
61
|
-
// If connection's access token is the same as the cache's, remove
|
|
62
|
-
// the token from the cache and connection.
|
|
63
|
-
this.cache.removeAccessToken();
|
|
64
|
-
delete connection.accessToken;
|
|
65
|
-
} else {
|
|
66
|
-
// If the connection's access token is different from the cache's, set
|
|
67
|
-
// the cache's token on the connection and do not remove from the
|
|
68
|
-
// cache.
|
|
69
|
-
connection.accessToken = this.cache.getAccessToken();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
await this.execute(connection, credentials);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Get the document to add for speculative authentication.
|
|
77
|
-
*/
|
|
78
|
-
async speculativeAuth(connection: Connection, credentials: MongoCredentials): Promise<Document> {
|
|
79
|
-
// The spec states only cached access tokens can use speculative auth.
|
|
80
|
-
if (!this.cache.hasAccessToken) {
|
|
81
|
-
return {};
|
|
82
|
-
}
|
|
83
|
-
const token = await this.getTokenFromCacheOrEnv(connection, credentials);
|
|
84
|
-
const document = finishCommandDocument(token);
|
|
85
|
-
document.db = credentials.source;
|
|
86
|
-
return { speculativeAuthenticate: document };
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Get the token from the cache or environment.
|
|
91
|
-
*/
|
|
92
|
-
private async getTokenFromCacheOrEnv(
|
|
93
|
-
connection: Connection,
|
|
94
|
-
credentials: MongoCredentials
|
|
95
|
-
): Promise<string> {
|
|
96
|
-
if (this.cache.hasAccessToken) {
|
|
97
|
-
const token = this.cache.getAccessToken();
|
|
98
|
-
// New connections won't have an access token so ensure we set here.
|
|
99
|
-
if (!connection.accessToken) {
|
|
100
|
-
connection.accessToken = token;
|
|
101
|
-
}
|
|
102
|
-
return token;
|
|
103
|
-
} else {
|
|
104
|
-
const token = await this.callback(credentials);
|
|
105
|
-
this.cache.put({ accessToken: token.access_token, expiresInSeconds: token.expires_in });
|
|
106
|
-
// Put the access token on the connection as well.
|
|
107
|
-
connection.accessToken = token.access_token;
|
|
108
|
-
return token.access_token;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Ensure the callback is only executed one at a time, and throttled to
|
|
114
|
-
* only once per 100ms.
|
|
115
|
-
*/
|
|
116
|
-
private withLock(callback: OIDCTokenFunction): OIDCTokenFunction {
|
|
117
|
-
let lock: Promise<any> = Promise.resolve();
|
|
118
|
-
return async (credentials: MongoCredentials): Promise<AccessToken> => {
|
|
119
|
-
// We do this to ensure that we would never return the result of the
|
|
120
|
-
// previous lock, only the current callback's value would get returned.
|
|
121
|
-
await lock;
|
|
122
|
-
lock = lock
|
|
123
|
-
|
|
124
|
-
.catch(() => null)
|
|
125
|
-
|
|
126
|
-
.then(async () => {
|
|
127
|
-
const difference = Date.now() - this.lastExecutionTime;
|
|
128
|
-
if (difference <= THROTTLE_MS) {
|
|
129
|
-
await setTimeout(THROTTLE_MS - difference);
|
|
130
|
-
}
|
|
131
|
-
this.lastExecutionTime = Date.now();
|
|
132
|
-
return await callback(credentials);
|
|
133
|
-
});
|
|
134
|
-
return await lock;
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Get the token from the environment or endpoint.
|
|
140
|
-
*/
|
|
141
|
-
abstract getToken(credentials: MongoCredentials): Promise<AccessToken>;
|
|
142
|
-
}
|