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.
Files changed (97) hide show
  1. package/lib/client-side-encryption/providers/azure.js +21 -6
  2. package/lib/client-side-encryption/providers/azure.js.map +1 -1
  3. package/lib/cmap/auth/mongo_credentials.js +24 -16
  4. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  5. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js +78 -0
  6. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -0
  7. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +74 -0
  8. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -0
  9. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +74 -135
  10. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -1
  11. package/lib/cmap/auth/mongodb_oidc/command_builders.js +45 -0
  12. package/lib/cmap/auth/mongodb_oidc/command_builders.js.map +1 -0
  13. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +46 -0
  14. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -0
  15. package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js +122 -0
  16. package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js.map +1 -0
  17. package/lib/cmap/auth/mongodb_oidc/machine_workflow.js +107 -0
  18. package/lib/cmap/auth/mongodb_oidc/machine_workflow.js.map +1 -0
  19. package/lib/cmap/auth/mongodb_oidc/token_cache.js +52 -0
  20. package/lib/cmap/auth/mongodb_oidc/token_cache.js.map +1 -0
  21. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +34 -0
  22. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -0
  23. package/lib/cmap/auth/mongodb_oidc.js +26 -24
  24. package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
  25. package/lib/cmap/auth/providers.js +0 -1
  26. package/lib/cmap/auth/providers.js.map +1 -1
  27. package/lib/cmap/connect.js +4 -4
  28. package/lib/cmap/connect.js.map +1 -1
  29. package/lib/cmap/connection.js.map +1 -1
  30. package/lib/cmap/connection_pool.js +1 -1
  31. package/lib/cmap/connection_pool.js.map +1 -1
  32. package/lib/connection_string.js +3 -0
  33. package/lib/connection_string.js.map +1 -1
  34. package/lib/error.js +57 -2
  35. package/lib/error.js.map +1 -1
  36. package/lib/index.js +5 -3
  37. package/lib/index.js.map +1 -1
  38. package/lib/mongo_client.js +1 -1
  39. package/lib/mongo_client.js.map +1 -1
  40. package/lib/mongo_client_auth_providers.js +34 -4
  41. package/lib/mongo_client_auth_providers.js.map +1 -1
  42. package/lib/sdam/server_description.js +10 -4
  43. package/lib/sdam/server_description.js.map +1 -1
  44. package/lib/sessions.js +10 -0
  45. package/lib/sessions.js.map +1 -1
  46. package/lib/utils.js +32 -2
  47. package/lib/utils.js.map +1 -1
  48. package/mongodb.d.ts +115 -25
  49. package/package.json +5 -4
  50. package/src/client-side-encryption/providers/azure.ts +21 -10
  51. package/src/cmap/auth/mongo_credentials.ts +41 -34
  52. package/src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts +82 -0
  53. package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +85 -0
  54. package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +96 -204
  55. package/src/cmap/auth/mongodb_oidc/command_builders.ts +54 -0
  56. package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +53 -0
  57. package/src/cmap/auth/mongodb_oidc/human_callback_workflow.ts +142 -0
  58. package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +137 -0
  59. package/src/cmap/auth/mongodb_oidc/token_cache.ts +62 -0
  60. package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +34 -0
  61. package/src/cmap/auth/mongodb_oidc.ts +79 -49
  62. package/src/cmap/auth/providers.ts +0 -1
  63. package/src/cmap/connect.ts +14 -4
  64. package/src/cmap/connection.ts +1 -0
  65. package/src/cmap/connection_pool.ts +2 -1
  66. package/src/connection_string.ts +3 -0
  67. package/src/error.ts +58 -1
  68. package/src/index.ts +8 -4
  69. package/src/mongo_client.ts +4 -1
  70. package/src/mongo_client_auth_providers.ts +44 -6
  71. package/src/sdam/server_description.ts +13 -4
  72. package/src/sessions.ts +10 -0
  73. package/src/utils.ts +33 -0
  74. package/lib/client-side-encryption/providers/utils.js +0 -35
  75. package/lib/client-side-encryption/providers/utils.js.map +0 -1
  76. package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js +0 -30
  77. package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js.map +0 -1
  78. package/lib/cmap/auth/mongodb_oidc/azure_service_workflow.js +0 -73
  79. package/lib/cmap/auth/mongodb_oidc/azure_service_workflow.js.map +0 -1
  80. package/lib/cmap/auth/mongodb_oidc/azure_token_cache.js +0 -49
  81. package/lib/cmap/auth/mongodb_oidc/azure_token_cache.js.map +0 -1
  82. package/lib/cmap/auth/mongodb_oidc/cache.js +0 -55
  83. package/lib/cmap/auth/mongodb_oidc/cache.js.map +0 -1
  84. package/lib/cmap/auth/mongodb_oidc/callback_lock_cache.js +0 -90
  85. package/lib/cmap/auth/mongodb_oidc/callback_lock_cache.js.map +0 -1
  86. package/lib/cmap/auth/mongodb_oidc/service_workflow.js +0 -43
  87. package/lib/cmap/auth/mongodb_oidc/service_workflow.js.map +0 -1
  88. package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js +0 -62
  89. package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js.map +0 -1
  90. package/src/client-side-encryption/providers/utils.ts +0 -37
  91. package/src/cmap/auth/mongodb_oidc/aws_service_workflow.ts +0 -29
  92. package/src/cmap/auth/mongodb_oidc/azure_service_workflow.ts +0 -86
  93. package/src/cmap/auth/mongodb_oidc/azure_token_cache.ts +0 -51
  94. package/src/cmap/auth/mongodb_oidc/cache.ts +0 -63
  95. package/src/cmap/auth/mongodb_oidc/callback_lock_cache.ts +0 -115
  96. package/src/cmap/auth/mongodb_oidc/service_workflow.ts +0 -49
  97. package/src/cmap/auth/mongodb_oidc/token_entry_cache.ts +0 -77
@@ -1 +0,0 @@
1
- {"version":3,"file":"token_entry_cache.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/token_entry_cache.ts"],"names":[],"mappings":";;;AACA,mCAAoD;AAEpD,+DAA+D;AAC/D,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAElC,gBAAgB;AAChB,MAAa,UAAW,SAAQ,0BAAkB;IAIhD;;OAEG;IACH,YAAY,WAA8B,EAAE,UAAyB,EAAE,UAAkB;QACvF,KAAK,CAAC,UAAU,CAAC,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAZD,gCAYC;AAED;;;GAGG;AACH,MAAa,eAAgB,SAAQ,aAAiB;IACpD;;OAEG;IACH,QAAQ,CACN,OAAe,EACf,QAAgB,EAChB,YAAoB,EACpB,WAA8B,EAC9B,UAAyB;QAEzB,MAAM,KAAK,GAAG,IAAI,UAAU,CAC1B,WAAW,EACX,UAAU,EACV,WAAW,CAAC,gBAAgB,IAAI,uBAAuB,CACxD,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,OAAe,EAAE,QAAgB,EAAE,YAAoB;QACjE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,OAAe,EAAE,QAAgB,EAAE,YAAoB;QAC9D,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED;;OAEG;IACH,oBAAoB;QAClB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE;YACvC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE;gBACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;aAC1B;SACF;IACH,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,OAAe,EAAE,QAAgB,EAAE,YAAoB;QAC9D,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC9D,CAAC;CACF;AAnDD,0CAmDC"}
@@ -1,37 +0,0 @@
1
- import * as http from 'http';
2
- import { clearTimeout, setTimeout } from 'timers';
3
-
4
- import { MongoCryptKMSRequestNetworkTimeoutError } from '../errors';
5
-
6
- /**
7
- * @internal
8
- */
9
- export function get(
10
- url: URL | string,
11
- options: http.RequestOptions = {}
12
- ): Promise<{ body: string; status: number | undefined }> {
13
- return new Promise((resolve, reject) => {
14
- /* eslint-disable prefer-const */
15
- let timeoutId: NodeJS.Timeout;
16
- const request = http
17
- .get(url, options, response => {
18
- response.setEncoding('utf8');
19
- let body = '';
20
- response.on('data', chunk => (body += chunk));
21
- response.on('end', () => {
22
- clearTimeout(timeoutId);
23
- resolve({ status: response.statusCode, body });
24
- });
25
- })
26
- .on('error', error => {
27
- clearTimeout(timeoutId);
28
- reject(error);
29
- })
30
- .end();
31
- timeoutId = setTimeout(() => {
32
- request.destroy(
33
- new MongoCryptKMSRequestNetworkTimeoutError(`request timed out after 10 seconds`)
34
- );
35
- }, 10000);
36
- });
37
- }
@@ -1,29 +0,0 @@
1
- import * as fs from 'fs';
2
-
3
- import { MongoAWSError } from '../../../error';
4
- import { ServiceWorkflow } from './service_workflow';
5
-
6
- /** Error for when the token is missing in the environment. */
7
- const TOKEN_MISSING_ERROR = 'AWS_WEB_IDENTITY_TOKEN_FILE must be set in the environment.';
8
-
9
- /**
10
- * Device workflow implementation for AWS.
11
- *
12
- * @internal
13
- */
14
- export class AwsServiceWorkflow extends ServiceWorkflow {
15
- constructor() {
16
- super();
17
- }
18
-
19
- /**
20
- * Get the token from the environment.
21
- */
22
- async getToken(): Promise<string> {
23
- const tokenFile = process.env.AWS_WEB_IDENTITY_TOKEN_FILE;
24
- if (!tokenFile) {
25
- throw new MongoAWSError(TOKEN_MISSING_ERROR);
26
- }
27
- return await fs.promises.readFile(tokenFile, 'utf8');
28
- }
29
- }
@@ -1,86 +0,0 @@
1
- import { MongoAzureError } from '../../../error';
2
- import { request } from '../../../utils';
3
- import type { MongoCredentials } from '../mongo_credentials';
4
- import { AzureTokenCache } from './azure_token_cache';
5
- import { ServiceWorkflow } from './service_workflow';
6
-
7
- /** Base URL for getting Azure tokens. */
8
- const AZURE_BASE_URL =
9
- 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01';
10
-
11
- /** Azure request headers. */
12
- const AZURE_HEADERS = Object.freeze({ Metadata: 'true', Accept: 'application/json' });
13
-
14
- /** Invalid endpoint result error. */
15
- const ENDPOINT_RESULT_ERROR =
16
- 'Azure endpoint did not return a value with only access_token and expires_in properties';
17
-
18
- /** Error for when the token audience is missing in the environment. */
19
- const TOKEN_AUDIENCE_MISSING_ERROR =
20
- 'TOKEN_AUDIENCE must be set in the auth mechanism properties when PROVIDER_NAME is azure.';
21
-
22
- /**
23
- * The Azure access token format.
24
- * @internal
25
- */
26
- export interface AzureAccessToken {
27
- access_token: string;
28
- expires_in: number;
29
- }
30
-
31
- /**
32
- * Device workflow implementation for Azure.
33
- *
34
- * @internal
35
- */
36
- export class AzureServiceWorkflow extends ServiceWorkflow {
37
- cache = new AzureTokenCache();
38
-
39
- /**
40
- * Get the token from the environment.
41
- */
42
- async getToken(credentials?: MongoCredentials): Promise<string> {
43
- const tokenAudience = credentials?.mechanismProperties.TOKEN_AUDIENCE;
44
- if (!tokenAudience) {
45
- throw new MongoAzureError(TOKEN_AUDIENCE_MISSING_ERROR);
46
- }
47
- let token;
48
- const entry = this.cache.getEntry(tokenAudience);
49
- if (entry?.isValid()) {
50
- token = entry.token;
51
- } else {
52
- this.cache.deleteEntry(tokenAudience);
53
- const response = await getAzureTokenData(tokenAudience);
54
- if (!isEndpointResultValid(response)) {
55
- throw new MongoAzureError(ENDPOINT_RESULT_ERROR);
56
- }
57
- this.cache.addEntry(tokenAudience, response);
58
- token = response.access_token;
59
- }
60
- return token;
61
- }
62
- }
63
-
64
- /**
65
- * Hit the Azure endpoint to get the token data.
66
- */
67
- async function getAzureTokenData(tokenAudience: string): Promise<AzureAccessToken> {
68
- const url = `${AZURE_BASE_URL}&resource=${tokenAudience}`;
69
- const data = await request(url, {
70
- json: true,
71
- headers: AZURE_HEADERS
72
- });
73
- return data as AzureAccessToken;
74
- }
75
-
76
- /**
77
- * Determines if a result returned from the endpoint is valid.
78
- * This means the result is not nullish, contains the access_token required field
79
- * and the expires_in required field.
80
- */
81
- function isEndpointResultValid(
82
- token: unknown
83
- ): token is { access_token: unknown; expires_in: unknown } {
84
- if (token == null || typeof token !== 'object') return false;
85
- return 'access_token' in token && 'expires_in' in token;
86
- }
@@ -1,51 +0,0 @@
1
- import type { AzureAccessToken } from './azure_service_workflow';
2
- import { Cache, ExpiringCacheEntry } from './cache';
3
-
4
- /** @internal */
5
- export class AzureTokenEntry extends ExpiringCacheEntry {
6
- token: string;
7
-
8
- /**
9
- * Instantiate the entry.
10
- */
11
- constructor(token: string, expiration: number) {
12
- super(expiration);
13
- this.token = token;
14
- }
15
- }
16
-
17
- /**
18
- * A cache of access tokens from Azure.
19
- * @internal
20
- */
21
- export class AzureTokenCache extends Cache<AzureTokenEntry> {
22
- /**
23
- * Add an entry to the cache.
24
- */
25
- addEntry(tokenAudience: string, token: AzureAccessToken): AzureTokenEntry {
26
- const entry = new AzureTokenEntry(token.access_token, token.expires_in);
27
- this.entries.set(tokenAudience, entry);
28
- return entry;
29
- }
30
-
31
- /**
32
- * Create a cache key.
33
- */
34
- cacheKey(tokenAudience: string): string {
35
- return tokenAudience;
36
- }
37
-
38
- /**
39
- * Delete an entry from the cache.
40
- */
41
- deleteEntry(tokenAudience: string): void {
42
- this.entries.delete(tokenAudience);
43
- }
44
-
45
- /**
46
- * Get an Azure token entry from the cache.
47
- */
48
- getEntry(tokenAudience: string): AzureTokenEntry | undefined {
49
- return this.entries.get(tokenAudience);
50
- }
51
- }
@@ -1,63 +0,0 @@
1
- /* 5 minutes in milliseconds */
2
- const EXPIRATION_BUFFER_MS = 300000;
3
-
4
- /**
5
- * An entry in a cache that can expire in a certain amount of time.
6
- */
7
- export abstract class ExpiringCacheEntry {
8
- expiration: number;
9
-
10
- /**
11
- * Create a new expiring token entry.
12
- */
13
- constructor(expiration: number) {
14
- this.expiration = this.expirationTime(expiration);
15
- }
16
- /**
17
- * The entry is still valid if the expiration is more than
18
- * 5 minutes from the expiration time.
19
- */
20
- isValid() {
21
- return this.expiration - Date.now() > EXPIRATION_BUFFER_MS;
22
- }
23
-
24
- /**
25
- * Get an expiration time in milliseconds past epoch.
26
- */
27
- private expirationTime(expiresInSeconds: number): number {
28
- return Date.now() + expiresInSeconds * 1000;
29
- }
30
- }
31
-
32
- /**
33
- * Base class for OIDC caches.
34
- */
35
- export abstract class Cache<T> {
36
- entries: Map<string, T>;
37
-
38
- /**
39
- * Create a new cache.
40
- */
41
- constructor() {
42
- this.entries = new Map<string, T>();
43
- }
44
-
45
- /**
46
- * Clear the cache.
47
- */
48
- clear() {
49
- this.entries.clear();
50
- }
51
-
52
- /**
53
- * Implement the cache key for the token.
54
- */
55
- abstract cacheKey(address: string, username: string, callbackHash: string): string;
56
-
57
- /**
58
- * Create a cache key from the address and username.
59
- */
60
- hashedCacheKey(address: string, username: string, callbackHash: string): string {
61
- return JSON.stringify([address, username, callbackHash]);
62
- }
63
- }
@@ -1,115 +0,0 @@
1
- import { MongoInvalidArgumentError } from '../../../error';
2
- import type { Connection } from '../../connection';
3
- import type { MongoCredentials } from '../mongo_credentials';
4
- import type {
5
- IdPServerInfo,
6
- IdPServerResponse,
7
- OIDCCallbackContext,
8
- OIDCRefreshFunction,
9
- OIDCRequestFunction
10
- } from '../mongodb_oidc';
11
- import { Cache } from './cache';
12
-
13
- /** Error message for when request callback is missing. */
14
- const REQUEST_CALLBACK_REQUIRED_ERROR =
15
- 'Auth mechanism property REQUEST_TOKEN_CALLBACK is required.';
16
- /* Counter for function "hashes".*/
17
- let FN_HASH_COUNTER = 0;
18
- /* No function present function */
19
- const NO_FUNCTION: OIDCRequestFunction = async () => ({ accessToken: 'test' });
20
- /* The map of function hashes */
21
- const FN_HASHES = new WeakMap<OIDCRequestFunction | OIDCRefreshFunction, number>();
22
- /* Put the no function hash in the map. */
23
- FN_HASHES.set(NO_FUNCTION, FN_HASH_COUNTER);
24
-
25
- /**
26
- * An entry of callbacks in the cache.
27
- */
28
- interface CallbacksEntry {
29
- requestCallback: OIDCRequestFunction;
30
- refreshCallback?: OIDCRefreshFunction;
31
- callbackHash: string;
32
- }
33
-
34
- /**
35
- * A cache of request and refresh callbacks per server/user.
36
- */
37
- export class CallbackLockCache extends Cache<CallbacksEntry> {
38
- /**
39
- * Get the callbacks for the connection and credentials. If an entry does not
40
- * exist a new one will get set.
41
- */
42
- getEntry(connection: Connection, credentials: MongoCredentials): CallbacksEntry {
43
- const requestCallback = credentials.mechanismProperties.REQUEST_TOKEN_CALLBACK;
44
- const refreshCallback = credentials.mechanismProperties.REFRESH_TOKEN_CALLBACK;
45
- if (!requestCallback) {
46
- throw new MongoInvalidArgumentError(REQUEST_CALLBACK_REQUIRED_ERROR);
47
- }
48
- const callbackHash = hashFunctions(requestCallback, refreshCallback);
49
- const key = this.cacheKey(connection.address, credentials.username, callbackHash);
50
- const entry = this.entries.get(key);
51
- if (entry) {
52
- return entry;
53
- }
54
- return this.addEntry(key, callbackHash, requestCallback, refreshCallback);
55
- }
56
-
57
- /**
58
- * Set locked callbacks on for connection and credentials.
59
- */
60
- private addEntry(
61
- key: string,
62
- callbackHash: string,
63
- requestCallback: OIDCRequestFunction,
64
- refreshCallback?: OIDCRefreshFunction
65
- ): CallbacksEntry {
66
- const entry = {
67
- requestCallback: withLock(requestCallback),
68
- refreshCallback: refreshCallback ? withLock(refreshCallback) : undefined,
69
- callbackHash: callbackHash
70
- };
71
- this.entries.set(key, entry);
72
- return entry;
73
- }
74
-
75
- /**
76
- * Create a cache key from the address and username.
77
- */
78
- cacheKey(address: string, username: string, callbackHash: string): string {
79
- return this.hashedCacheKey(address, username, callbackHash);
80
- }
81
- }
82
-
83
- /**
84
- * Ensure the callback is only executed one at a time.
85
- */
86
- function withLock(callback: OIDCRequestFunction | OIDCRefreshFunction) {
87
- let lock: Promise<any> = Promise.resolve();
88
- return async (info: IdPServerInfo, context: OIDCCallbackContext): Promise<IdPServerResponse> => {
89
- await lock;
90
- // eslint-disable-next-line github/no-then
91
- lock = lock.then(() => callback(info, context));
92
- return await lock;
93
- };
94
- }
95
-
96
- /**
97
- * Get the hash string for the request and refresh functions.
98
- */
99
- function hashFunctions(requestFn: OIDCRequestFunction, refreshFn?: OIDCRefreshFunction): string {
100
- let requestHash = FN_HASHES.get(requestFn);
101
- let refreshHash = FN_HASHES.get(refreshFn ?? NO_FUNCTION);
102
- if (requestHash == null) {
103
- // Create a new one for the function and put it in the map.
104
- FN_HASH_COUNTER++;
105
- requestHash = FN_HASH_COUNTER;
106
- FN_HASHES.set(requestFn, FN_HASH_COUNTER);
107
- }
108
- if (refreshHash == null && refreshFn) {
109
- // Create a new one for the function and put it in the map.
110
- FN_HASH_COUNTER++;
111
- refreshHash = FN_HASH_COUNTER;
112
- FN_HASHES.set(refreshFn, FN_HASH_COUNTER);
113
- }
114
- return `${requestHash}-${refreshHash}`;
115
- }
@@ -1,49 +0,0 @@
1
- import { BSON, type Document } from 'bson';
2
-
3
- import { ns } from '../../../utils';
4
- import type { Connection } from '../../connection';
5
- import type { MongoCredentials } from '../mongo_credentials';
6
- import type { Workflow } from '../mongodb_oidc';
7
- import { AuthMechanism } from '../providers';
8
-
9
- /**
10
- * Common behaviour for OIDC device workflows.
11
- * @internal
12
- */
13
- export abstract class ServiceWorkflow implements Workflow {
14
- /**
15
- * Execute the workflow. Looks for AWS_WEB_IDENTITY_TOKEN_FILE in the environment
16
- * and then attempts to read the token from that path.
17
- */
18
- async execute(connection: Connection, credentials: MongoCredentials): Promise<Document> {
19
- const token = await this.getToken(credentials);
20
- const command = commandDocument(token);
21
- return await connection.command(ns(credentials.source), command, undefined);
22
- }
23
-
24
- /**
25
- * Get the document to add for speculative authentication.
26
- */
27
- async speculativeAuth(credentials: MongoCredentials): Promise<Document> {
28
- const token = await this.getToken(credentials);
29
- const document = commandDocument(token);
30
- document.db = credentials.source;
31
- return { speculativeAuthenticate: document };
32
- }
33
-
34
- /**
35
- * Get the token from the environment or endpoint.
36
- */
37
- abstract getToken(credentials: MongoCredentials): Promise<string>;
38
- }
39
-
40
- /**
41
- * Create the saslStart command document.
42
- */
43
- export function commandDocument(token: string): Document {
44
- return {
45
- saslStart: 1,
46
- mechanism: AuthMechanism.MONGODB_OIDC,
47
- payload: BSON.serialize({ jwt: token })
48
- };
49
- }
@@ -1,77 +0,0 @@
1
- import type { IdPServerInfo, IdPServerResponse } from '../mongodb_oidc';
2
- import { Cache, ExpiringCacheEntry } from './cache';
3
-
4
- /* Default expiration is now for when no expiration provided */
5
- const DEFAULT_EXPIRATION_SECS = 0;
6
-
7
- /** @internal */
8
- export class TokenEntry extends ExpiringCacheEntry {
9
- tokenResult: IdPServerResponse;
10
- serverInfo: IdPServerInfo;
11
-
12
- /**
13
- * Instantiate the entry.
14
- */
15
- constructor(tokenResult: IdPServerResponse, serverInfo: IdPServerInfo, expiration: number) {
16
- super(expiration);
17
- this.tokenResult = tokenResult;
18
- this.serverInfo = serverInfo;
19
- }
20
- }
21
-
22
- /**
23
- * Cache of OIDC token entries.
24
- * @internal
25
- */
26
- export class TokenEntryCache extends Cache<TokenEntry> {
27
- /**
28
- * Set an entry in the token cache.
29
- */
30
- addEntry(
31
- address: string,
32
- username: string,
33
- callbackHash: string,
34
- tokenResult: IdPServerResponse,
35
- serverInfo: IdPServerInfo
36
- ): TokenEntry {
37
- const entry = new TokenEntry(
38
- tokenResult,
39
- serverInfo,
40
- tokenResult.expiresInSeconds ?? DEFAULT_EXPIRATION_SECS
41
- );
42
- this.entries.set(this.cacheKey(address, username, callbackHash), entry);
43
- return entry;
44
- }
45
-
46
- /**
47
- * Delete an entry from the cache.
48
- */
49
- deleteEntry(address: string, username: string, callbackHash: string): void {
50
- this.entries.delete(this.cacheKey(address, username, callbackHash));
51
- }
52
-
53
- /**
54
- * Get an entry from the cache.
55
- */
56
- getEntry(address: string, username: string, callbackHash: string): TokenEntry | undefined {
57
- return this.entries.get(this.cacheKey(address, username, callbackHash));
58
- }
59
-
60
- /**
61
- * Delete all expired entries from the cache.
62
- */
63
- deleteExpiredEntries(): void {
64
- for (const [key, entry] of this.entries) {
65
- if (!entry.isValid()) {
66
- this.entries.delete(key);
67
- }
68
- }
69
- }
70
-
71
- /**
72
- * Create a cache key from the address and username.
73
- */
74
- cacheKey(address: string, username: string, callbackHash: string): string {
75
- return this.hashedCacheKey(address, username, callbackHash);
76
- }
77
- }