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
package/mongodb.d.ts CHANGED
@@ -502,7 +502,6 @@ export declare const AuthMechanism: Readonly<{
502
502
  readonly MONGODB_SCRAM_SHA1: "SCRAM-SHA-1";
503
503
  readonly MONGODB_SCRAM_SHA256: "SCRAM-SHA-256";
504
504
  readonly MONGODB_X509: "MONGODB-X509";
505
- /** @experimental */
506
505
  readonly MONGODB_OIDC: "MONGODB-OIDC";
507
506
  }>;
508
507
 
@@ -516,16 +515,16 @@ export declare interface AuthMechanismProperties extends Document {
516
515
  SERVICE_REALM?: string;
517
516
  CANONICALIZE_HOST_NAME?: GSSAPICanonicalizationValue;
518
517
  AWS_SESSION_TOKEN?: string;
519
- /** @experimental */
520
- REQUEST_TOKEN_CALLBACK?: OIDCRequestFunction;
521
- /** @experimental */
522
- REFRESH_TOKEN_CALLBACK?: OIDCRefreshFunction;
523
- /** @experimental */
524
- PROVIDER_NAME?: 'aws' | 'azure';
525
- /** @experimental */
518
+ /** A user provided OIDC machine callback function. */
519
+ OIDC_CALLBACK?: OIDCCallbackFunction;
520
+ /** A user provided OIDC human interacted callback function. */
521
+ OIDC_HUMAN_CALLBACK?: OIDCCallbackFunction;
522
+ /** The OIDC environment. Note that 'test' is for internal use only. */
523
+ ENVIRONMENT?: 'test' | 'azure' | 'gcp';
524
+ /** Allowed hosts that OIDC auth can connect to. */
526
525
  ALLOWED_HOSTS?: string[];
527
- /** @experimental */
528
- TOKEN_AUDIENCE?: string;
526
+ /** The resource token for OIDC auth in Azure and GCP. */
527
+ TOKEN_RESOURCE?: string;
529
528
  }
530
529
 
531
530
  /* Excluded from this release type: AuthProvider */
@@ -2010,6 +2009,11 @@ export declare class ClientSession extends TypedEventEmitter<ClientSessionEvents
2010
2009
  /**
2011
2010
  * Starts a new transaction with the given options.
2012
2011
  *
2012
+ * @remarks
2013
+ * **IMPORTANT**: Running operations in parallel is not supported during a transaction. The use of `Promise.all`,
2014
+ * `Promise.allSettled`, `Promise.race`, etc to parallelize operations inside a transaction is
2015
+ * undefined behaviour.
2016
+ *
2013
2017
  * @param options - Options for the transaction
2014
2018
  */
2015
2019
  startTransaction(options?: TransactionOptions): void;
@@ -2030,6 +2034,11 @@ export declare class ClientSession extends TypedEventEmitter<ClientSessionEvents
2030
2034
  *
2031
2035
  * **IMPORTANT:** This method requires the function passed in to return a Promise. That promise must be made by `await`-ing all operations in such a way that rejections are propagated to the returned promise.
2032
2036
  *
2037
+ * **IMPORTANT:** Running operations in parallel is not supported during a transaction. The use of `Promise.all`,
2038
+ * `Promise.allSettled`, `Promise.race`, etc to parallelize operations inside a transaction is
2039
+ * undefined behaviour.
2040
+ *
2041
+ *
2033
2042
  * @remarks
2034
2043
  * - If all operations successfully complete and the `commitTransaction` operation is successful, then the provided function will return the result of the provided function.
2035
2044
  * - If the transaction is unable to complete or an error is thrown from within the provided function, then the provided function will throw an error.
@@ -4281,22 +4290,33 @@ export declare class HostAddress {
4281
4290
  }
4282
4291
 
4283
4292
  /**
4293
+ * The information returned by the server on the IDP server.
4284
4294
  * @public
4285
- * @experimental
4286
4295
  */
4287
- export declare interface IdPServerInfo {
4296
+ export declare interface IdPInfo {
4297
+ /**
4298
+ * A URL which describes the Authentication Server. This identifier should
4299
+ * be the iss of provided access tokens, and be viable for RFC8414 metadata
4300
+ * discovery and RFC9207 identification.
4301
+ */
4288
4302
  issuer: string;
4303
+ /** A unique client ID for this OIDC client. */
4289
4304
  clientId: string;
4305
+ /** A list of additional scopes to request from IdP. */
4290
4306
  requestScopes?: string[];
4291
4307
  }
4292
4308
 
4293
4309
  /**
4310
+ * The response from the IdP server with the access token and
4311
+ * optional expiration time and refresh token.
4294
4312
  * @public
4295
- * @experimental
4296
4313
  */
4297
4314
  export declare interface IdPServerResponse {
4315
+ /** The OIDC access token. */
4298
4316
  accessToken: string;
4317
+ /** The time when the access token expires. For future use. */
4299
4318
  expiresInSeconds?: number;
4319
+ /** The refresh token, if applicable, to be used by the callback to request a new token from the issuer. */
4300
4320
  refreshToken?: string;
4301
4321
  }
4302
4322
 
@@ -4793,7 +4813,7 @@ export declare class MongoAWSError extends MongoRuntimeError {
4793
4813
  * @public
4794
4814
  * @category Error
4795
4815
  */
4796
- export declare class MongoAzureError extends MongoRuntimeError {
4816
+ export declare class MongoAzureError extends MongoOIDCError {
4797
4817
  /**
4798
4818
  * **Do not use this constructor!**
4799
4819
  *
@@ -5564,6 +5584,29 @@ export declare class MongoExpiredSessionError extends MongoAPIError {
5564
5584
  get name(): string;
5565
5585
  }
5566
5586
 
5587
+ /**
5588
+ * A error generated when the user attempts to authenticate
5589
+ * via GCP, but fails.
5590
+ *
5591
+ * @public
5592
+ * @category Error
5593
+ */
5594
+ export declare class MongoGCPError extends MongoOIDCError {
5595
+ /**
5596
+ * **Do not use this constructor!**
5597
+ *
5598
+ * Meant for internal use only.
5599
+ *
5600
+ * @remarks
5601
+ * This class is only meant to be constructed within the driver. This constructor is
5602
+ * not subject to semantic versioning compatibility guarantees and may change at any time.
5603
+ *
5604
+ * @public
5605
+ **/
5606
+ constructor(message: string);
5607
+ get name(): string;
5608
+ }
5609
+
5567
5610
  /**
5568
5611
  * An error generated when a malformed or invalid chunk is
5569
5612
  * encountered when reading from a GridFSStream.
@@ -5793,6 +5836,29 @@ export declare class MongoNotConnectedError extends MongoAPIError {
5793
5836
  get name(): string;
5794
5837
  }
5795
5838
 
5839
+ /**
5840
+ * A error generated when the user attempts to authenticate
5841
+ * via OIDC callbacks, but fails.
5842
+ *
5843
+ * @public
5844
+ * @category Error
5845
+ */
5846
+ export declare class MongoOIDCError extends MongoRuntimeError {
5847
+ /**
5848
+ * **Do not use this constructor!**
5849
+ *
5850
+ * Meant for internal use only.
5851
+ *
5852
+ * @remarks
5853
+ * This class is only meant to be constructed within the driver. This constructor is
5854
+ * not subject to semantic versioning compatibility guarantees and may change at any time.
5855
+ *
5856
+ * @public
5857
+ **/
5858
+ constructor(message: string);
5859
+ get name(): string;
5860
+ }
5861
+
5796
5862
  /**
5797
5863
  * Parsed Mongo Client Options.
5798
5864
  *
@@ -5828,6 +5894,7 @@ export declare interface MongoOptions extends Required<Pick<MongoClientOptions,
5828
5894
  metadata: ClientMetadata;
5829
5895
  /* Excluded from this release type: extendedMetadata */
5830
5896
  /* Excluded from this release type: autoEncrypter */
5897
+ /* Excluded from this release type: tokenCache */
5831
5898
  proxyHost?: string;
5832
5899
  proxyPort?: number;
5833
5900
  proxyUsername?: string;
@@ -6230,27 +6297,46 @@ export declare type NumericType = IntegerType | Decimal128 | Double;
6230
6297
  export { ObjectId }
6231
6298
 
6232
6299
  /**
6300
+ * The signature of the human or machine callback functions.
6233
6301
  * @public
6234
- * @experimental
6235
6302
  */
6236
- export declare interface OIDCCallbackContext {
6237
- refreshToken?: string;
6238
- timeoutSeconds?: number;
6239
- timeoutContext?: AbortSignal;
6240
- version: number;
6241
- }
6303
+ export declare type OIDCCallbackFunction = (params: OIDCCallbackParams) => Promise<OIDCResponse>;
6242
6304
 
6243
6305
  /**
6306
+ * The parameters that the driver provides to the user supplied
6307
+ * human or machine callback.
6308
+ *
6309
+ * The version number is used to communicate callback API changes that are not breaking but that
6310
+ * users may want to know about and review their implementation. Users may wish to check the version
6311
+ * number and throw an error if their expected version number and the one provided do not match.
6244
6312
  * @public
6245
- * @experimental
6246
6313
  */
6247
- export declare type OIDCRefreshFunction = (info: IdPServerInfo, context: OIDCCallbackContext) => Promise<IdPServerResponse>;
6314
+ export declare interface OIDCCallbackParams {
6315
+ /** Optional username. */
6316
+ username?: string;
6317
+ /** The context in which to timeout the OIDC callback. */
6318
+ timeoutContext: AbortSignal;
6319
+ /** The current OIDC API version. */
6320
+ version: 1;
6321
+ /** The IdP information returned from the server. */
6322
+ idpInfo?: IdPInfo;
6323
+ /** The refresh token, if applicable, to be used by the callback to request a new token from the issuer. */
6324
+ refreshToken?: string;
6325
+ }
6248
6326
 
6249
6327
  /**
6328
+ * The response required to be returned from the machine or
6329
+ * human callback workflows' callback.
6250
6330
  * @public
6251
- * @experimental
6252
6331
  */
6253
- export declare type OIDCRequestFunction = (info: IdPServerInfo, context: OIDCCallbackContext) => Promise<IdPServerResponse>;
6332
+ export declare interface OIDCResponse {
6333
+ /** The OIDC access token. */
6334
+ accessToken: string;
6335
+ /** The time when the access token expires. For future use. */
6336
+ expiresInSeconds?: number;
6337
+ /** The refresh token, if applicable, to be used by the callback to request a new token from the issuer. */
6338
+ refreshToken?: string;
6339
+ }
6254
6340
 
6255
6341
  /* Excluded from this release type: OnDemandDocument */
6256
6342
 
@@ -7159,6 +7245,8 @@ export declare interface TimeSeriesCollectionOptions extends Document {
7159
7245
 
7160
7246
  export { Timestamp }
7161
7247
 
7248
+ /* Excluded from this release type: TokenCache */
7249
+
7162
7250
  /* Excluded from this release type: Topology */
7163
7251
 
7164
7252
  /* Excluded from this release type: TOPOLOGY_CLOSED */
@@ -7587,6 +7675,8 @@ export declare type WithSessionCallback<T = unknown> = (session: ClientSession)
7587
7675
  /** @public */
7588
7676
  export declare type WithTransactionCallback<T = any> = (session: ClientSession) => Promise<T>;
7589
7677
 
7678
+ /* Excluded from this release type: Workflow */
7679
+
7590
7680
  /**
7591
7681
  * A MongoDB WriteConcern, which describes the level of acknowledgement
7592
7682
  * requested from MongoDB for write operations.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "6.6.2",
3
+ "version": "6.7.0",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -68,7 +68,6 @@
68
68
  "@microsoft/api-extractor": "^7.43.1",
69
69
  "@microsoft/tsdoc-config": "^0.16.2",
70
70
  "@mongodb-js/zstd": "^1.2.0",
71
- "@octokit/core": "^6.1.2",
72
71
  "@types/chai": "^4.3.14",
73
72
  "@types/chai-subset": "^1.3.5",
74
73
  "@types/express": "^4.17.21",
@@ -149,8 +148,10 @@
149
148
  "check:drivers-atlas-testing": "mocha --config test/mocha_mongodb.json test/atlas/drivers_atlas_testing.test.ts",
150
149
  "check:adl": "mocha --config test/mocha_mongodb.json test/manual/atlas-data-lake-testing",
151
150
  "check:aws": "nyc mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_aws.test.ts",
152
- "check:oidc": "mocha --config test/mocha_mongodb.json test/manual/mongodb_oidc.prose.test.ts",
153
- "check:oidc-azure": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_azure.prose.test.ts",
151
+ "check:oidc-auth": "mocha --config test/mocha_mongodb.json test/integration/auth/auth.spec.test.ts",
152
+ "check:oidc-test": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc.prose.test.ts",
153
+ "check:oidc-azure": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_azure.prose.05.test.ts",
154
+ "check:oidc-gcp": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_gcp.prose.06.test.ts",
154
155
  "check:ocsp": "mocha --config test/manual/mocharc.json test/manual/ocsp_support.test.js",
155
156
  "check:kerberos": "nyc mocha --config test/manual/mocharc.json test/manual/kerberos.test.ts",
156
157
  "check:tls": "mocha --config test/manual/mocharc.json test/manual/tls_support.test.ts",
@@ -1,9 +1,12 @@
1
1
  import { type Document } from '../../bson';
2
- import { MongoCryptAzureKMSRequestError, MongoCryptKMSRequestNetworkTimeoutError } from '../errors';
2
+ import { MongoNetworkTimeoutError } from '../../error';
3
+ import { get } from '../../utils';
4
+ import { MongoCryptAzureKMSRequestError } from '../errors';
3
5
  import { type KMSProviders } from './index';
4
- import { get } from './utils';
5
6
 
6
7
  const MINIMUM_TOKEN_REFRESH_IN_MILLISECONDS = 6000;
8
+ /** Base URL for getting Azure tokens. */
9
+ export const AZURE_BASE_URL = 'http://169.254.169.254/metadata/identity/oauth2/token?';
7
10
 
8
11
  /**
9
12
  * The access token that libmongocrypt expects for Azure kms.
@@ -113,6 +116,19 @@ export interface AzureKMSRequestOptions {
113
116
  url?: URL | string;
114
117
  }
115
118
 
119
+ /**
120
+ * @internal
121
+ * Get the Azure endpoint URL.
122
+ */
123
+ export function addAzureParams(url: URL, resource: string, username?: string): URL {
124
+ url.searchParams.append('api-version', '2018-02-01');
125
+ url.searchParams.append('resource', resource);
126
+ if (username) {
127
+ url.searchParams.append('client_id', username);
128
+ }
129
+ return url;
130
+ }
131
+
116
132
  /**
117
133
  * @internal
118
134
  *
@@ -123,13 +139,8 @@ export function prepareRequest(options: AzureKMSRequestOptions): {
123
139
  headers: Document;
124
140
  url: URL;
125
141
  } {
126
- const url = new URL(
127
- options.url?.toString() ?? 'http://169.254.169.254/metadata/identity/oauth2/token'
128
- );
129
-
130
- url.searchParams.append('api-version', '2018-02-01');
131
- url.searchParams.append('resource', 'https://vault.azure.net');
132
-
142
+ const url = new URL(options.url?.toString() ?? AZURE_BASE_URL);
143
+ addAzureParams(url, 'https://vault.azure.net');
133
144
  const headers = { ...options.headers, 'Content-Type': 'application/json', Metadata: true };
134
145
  return { headers, url };
135
146
  }
@@ -152,7 +163,7 @@ export async function fetchAzureKMSToken(
152
163
  const response = await get(url, { headers });
153
164
  return await parseResponse(response);
154
165
  } catch (error) {
155
- if (error instanceof MongoCryptKMSRequestNetworkTimeoutError) {
166
+ if (error instanceof MongoNetworkTimeoutError) {
156
167
  throw new MongoCryptAzureKMSRequestError(`[Azure KMS] ${error.message}`);
157
168
  }
158
169
  throw error;
@@ -3,12 +3,11 @@
3
3
  import type { Document } from '../../bson';
4
4
  import {
5
5
  MongoAPIError,
6
- MongoAzureError,
7
6
  MongoInvalidArgumentError,
8
7
  MongoMissingCredentialsError
9
8
  } from '../../error';
10
9
  import { GSSAPICanonicalizationValue } from './gssapi';
11
- import type { OIDCRefreshFunction, OIDCRequestFunction } from './mongodb_oidc';
10
+ import type { OIDCCallbackFunction } from './mongodb_oidc';
12
11
  import { AUTH_MECHS_AUTH_SRC_EXTERNAL, AuthMechanism } from './providers';
13
12
 
14
13
  // https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst
@@ -32,12 +31,17 @@ function getDefaultAuthMechanism(hello: Document | null): AuthMechanism {
32
31
  return AuthMechanism.MONGODB_CR;
33
32
  }
34
33
 
35
- const ALLOWED_PROVIDER_NAMES: AuthMechanismProperties['PROVIDER_NAME'][] = ['aws', 'azure'];
34
+ const ALLOWED_ENVIRONMENT_NAMES: AuthMechanismProperties['ENVIRONMENT'][] = [
35
+ 'test',
36
+ 'azure',
37
+ 'gcp'
38
+ ];
36
39
  const ALLOWED_HOSTS_ERROR = 'Auth mechanism property ALLOWED_HOSTS must be an array of strings.';
37
40
 
38
41
  /** @internal */
39
42
  export const DEFAULT_ALLOWED_HOSTS = [
40
43
  '*.mongodb.net',
44
+ '*.mongodb-qa.net',
41
45
  '*.mongodb-dev.net',
42
46
  '*.mongodbgov.net',
43
47
  'localhost',
@@ -46,8 +50,8 @@ export const DEFAULT_ALLOWED_HOSTS = [
46
50
  ];
47
51
 
48
52
  /** Error for when the token audience is missing in the environment. */
49
- const TOKEN_AUDIENCE_MISSING_ERROR =
50
- 'TOKEN_AUDIENCE must be set in the auth mechanism properties when PROVIDER_NAME is azure.';
53
+ const TOKEN_RESOURCE_MISSING_ERROR =
54
+ 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure or gcp.';
51
55
 
52
56
  /** @public */
53
57
  export interface AuthMechanismProperties extends Document {
@@ -56,16 +60,16 @@ export interface AuthMechanismProperties extends Document {
56
60
  SERVICE_REALM?: string;
57
61
  CANONICALIZE_HOST_NAME?: GSSAPICanonicalizationValue;
58
62
  AWS_SESSION_TOKEN?: string;
59
- /** @experimental */
60
- REQUEST_TOKEN_CALLBACK?: OIDCRequestFunction;
61
- /** @experimental */
62
- REFRESH_TOKEN_CALLBACK?: OIDCRefreshFunction;
63
- /** @experimental */
64
- PROVIDER_NAME?: 'aws' | 'azure';
65
- /** @experimental */
63
+ /** A user provided OIDC machine callback function. */
64
+ OIDC_CALLBACK?: OIDCCallbackFunction;
65
+ /** A user provided OIDC human interacted callback function. */
66
+ OIDC_HUMAN_CALLBACK?: OIDCCallbackFunction;
67
+ /** The OIDC environment. Note that 'test' is for internal use only. */
68
+ ENVIRONMENT?: 'test' | 'azure' | 'gcp';
69
+ /** Allowed hosts that OIDC auth can connect to. */
66
70
  ALLOWED_HOSTS?: string[];
67
- /** @experimental */
68
- TOKEN_AUDIENCE?: string;
71
+ /** The resource token for OIDC auth in Azure and GCP. */
72
+ TOKEN_RESOURCE?: string;
69
73
  }
70
74
 
71
75
  /** @public */
@@ -179,45 +183,48 @@ export class MongoCredentials {
179
183
  }
180
184
 
181
185
  if (this.mechanism === AuthMechanism.MONGODB_OIDC) {
182
- if (this.username && this.mechanismProperties.PROVIDER_NAME) {
186
+ if (
187
+ this.username &&
188
+ this.mechanismProperties.ENVIRONMENT &&
189
+ this.mechanismProperties.ENVIRONMENT !== 'azure'
190
+ ) {
183
191
  throw new MongoInvalidArgumentError(
184
- `username and PROVIDER_NAME may not be used together for mechanism '${this.mechanism}'.`
192
+ `username and ENVIRONMENT '${this.mechanismProperties.ENVIRONMENT}' may not be used together for mechanism '${this.mechanism}'.`
185
193
  );
186
194
  }
187
195
 
188
- if (
189
- this.mechanismProperties.PROVIDER_NAME === 'azure' &&
190
- !this.mechanismProperties.TOKEN_AUDIENCE
191
- ) {
192
- throw new MongoAzureError(TOKEN_AUDIENCE_MISSING_ERROR);
196
+ if (this.username && this.password) {
197
+ throw new MongoInvalidArgumentError(
198
+ `No password is allowed in ENVIRONMENT '${this.mechanismProperties.ENVIRONMENT}' for '${this.mechanism}'.`
199
+ );
193
200
  }
194
201
 
195
202
  if (
196
- this.mechanismProperties.PROVIDER_NAME &&
197
- !ALLOWED_PROVIDER_NAMES.includes(this.mechanismProperties.PROVIDER_NAME)
203
+ (this.mechanismProperties.ENVIRONMENT === 'azure' ||
204
+ this.mechanismProperties.ENVIRONMENT === 'gcp') &&
205
+ !this.mechanismProperties.TOKEN_RESOURCE
198
206
  ) {
199
- throw new MongoInvalidArgumentError(
200
- `Currently only a PROVIDER_NAME in ${ALLOWED_PROVIDER_NAMES.join(
201
- ','
202
- )} is supported for mechanism '${this.mechanism}'.`
203
- );
207
+ throw new MongoInvalidArgumentError(TOKEN_RESOURCE_MISSING_ERROR);
204
208
  }
205
209
 
206
210
  if (
207
- this.mechanismProperties.REFRESH_TOKEN_CALLBACK &&
208
- !this.mechanismProperties.REQUEST_TOKEN_CALLBACK
211
+ this.mechanismProperties.ENVIRONMENT &&
212
+ !ALLOWED_ENVIRONMENT_NAMES.includes(this.mechanismProperties.ENVIRONMENT)
209
213
  ) {
210
214
  throw new MongoInvalidArgumentError(
211
- `A REQUEST_TOKEN_CALLBACK must be provided when using a REFRESH_TOKEN_CALLBACK for mechanism '${this.mechanism}'`
215
+ `Currently only a ENVIRONMENT in ${ALLOWED_ENVIRONMENT_NAMES.join(
216
+ ','
217
+ )} is supported for mechanism '${this.mechanism}'.`
212
218
  );
213
219
  }
214
220
 
215
221
  if (
216
- !this.mechanismProperties.PROVIDER_NAME &&
217
- !this.mechanismProperties.REQUEST_TOKEN_CALLBACK
222
+ !this.mechanismProperties.ENVIRONMENT &&
223
+ !this.mechanismProperties.OIDC_CALLBACK &&
224
+ !this.mechanismProperties.OIDC_HUMAN_CALLBACK
218
225
  ) {
219
226
  throw new MongoInvalidArgumentError(
220
- `Either a PROVIDER_NAME or a REQUEST_TOKEN_CALLBACK must be specified for mechanism '${this.mechanism}'.`
227
+ `Either a ENVIRONMENT, OIDC_CALLBACK, or OIDC_HUMAN_CALLBACK must be specified for mechanism '${this.mechanism}'.`
221
228
  );
222
229
  }
223
230
 
@@ -0,0 +1,82 @@
1
+ import { MONGODB_ERROR_CODES, MongoError, MongoOIDCError } from '../../../error';
2
+ import { Timeout, TimeoutError } from '../../../timeout';
3
+ import { type Connection } from '../../connection';
4
+ import { type MongoCredentials } from '../mongo_credentials';
5
+ import {
6
+ OIDC_VERSION,
7
+ type OIDCCallbackFunction,
8
+ type OIDCCallbackParams,
9
+ type OIDCResponse
10
+ } from '../mongodb_oidc';
11
+ import { AUTOMATED_TIMEOUT_MS, CallbackWorkflow } from './callback_workflow';
12
+ import { type TokenCache } from './token_cache';
13
+
14
+ /**
15
+ * Class implementing behaviour for the non human callback workflow.
16
+ * @internal
17
+ */
18
+ export class AutomatedCallbackWorkflow extends CallbackWorkflow {
19
+ /**
20
+ * Instantiate the human callback workflow.
21
+ */
22
+ constructor(cache: TokenCache, callback: OIDCCallbackFunction) {
23
+ super(cache, callback);
24
+ }
25
+
26
+ /**
27
+ * Execute the OIDC callback workflow.
28
+ */
29
+ async execute(connection: Connection, credentials: MongoCredentials): Promise<void> {
30
+ // If there is a cached access token, try to authenticate with it. If
31
+ // authentication fails with an Authentication error (18),
32
+ // invalidate the access token, fetch a new access token, and try
33
+ // to authenticate again.
34
+ // If the server fails for any other reason, do not clear the cache.
35
+ if (this.cache.hasAccessToken) {
36
+ const token = this.cache.getAccessToken();
37
+ try {
38
+ return await this.finishAuthentication(connection, credentials, token);
39
+ } catch (error) {
40
+ if (
41
+ error instanceof MongoError &&
42
+ error.code === MONGODB_ERROR_CODES.AuthenticationFailed
43
+ ) {
44
+ this.cache.removeAccessToken();
45
+ return await this.execute(connection, credentials);
46
+ } else {
47
+ throw error;
48
+ }
49
+ }
50
+ }
51
+ const response = await this.fetchAccessToken(credentials);
52
+ this.cache.put(response);
53
+ connection.accessToken = response.accessToken;
54
+ await this.finishAuthentication(connection, credentials, response.accessToken);
55
+ }
56
+
57
+ /**
58
+ * Fetches the access token using the callback.
59
+ */
60
+ protected async fetchAccessToken(credentials: MongoCredentials): Promise<OIDCResponse> {
61
+ const controller = new AbortController();
62
+ const params: OIDCCallbackParams = {
63
+ timeoutContext: controller.signal,
64
+ version: OIDC_VERSION
65
+ };
66
+ if (credentials.username) {
67
+ params.username = credentials.username;
68
+ }
69
+ const timeout = Timeout.expires(AUTOMATED_TIMEOUT_MS);
70
+ try {
71
+ return await Promise.race([this.executeAndValidateCallback(params), timeout]);
72
+ } catch (error) {
73
+ if (TimeoutError.is(error)) {
74
+ controller.abort();
75
+ throw new MongoOIDCError(`OIDC callback timed out after ${AUTOMATED_TIMEOUT_MS}ms.`);
76
+ }
77
+ throw error;
78
+ } finally {
79
+ timeout.clear();
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,85 @@
1
+ import { addAzureParams, AZURE_BASE_URL } from '../../../client-side-encryption/providers/azure';
2
+ import { MongoAzureError } from '../../../error';
3
+ import { get } from '../../../utils';
4
+ import type { MongoCredentials } from '../mongo_credentials';
5
+ import { type AccessToken, MachineWorkflow } from './machine_workflow';
6
+ import { type TokenCache } from './token_cache';
7
+
8
+ /** Azure request headers. */
9
+ const AZURE_HEADERS = Object.freeze({ Metadata: 'true', Accept: 'application/json' });
10
+
11
+ /** Invalid endpoint result error. */
12
+ const ENDPOINT_RESULT_ERROR =
13
+ 'Azure endpoint did not return a value with only access_token and expires_in properties';
14
+
15
+ /** Error for when the token audience is missing in the environment. */
16
+ const TOKEN_RESOURCE_MISSING_ERROR =
17
+ 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure.';
18
+
19
+ /**
20
+ * Device workflow implementation for Azure.
21
+ *
22
+ * @internal
23
+ */
24
+ export class AzureMachineWorkflow extends MachineWorkflow {
25
+ /**
26
+ * Instantiate the machine workflow.
27
+ */
28
+ constructor(cache: TokenCache) {
29
+ super(cache);
30
+ }
31
+
32
+ /**
33
+ * Get the token from the environment.
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;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Hit the Azure endpoint to get the token data.
51
+ */
52
+ async function getAzureTokenData(tokenAudience: string, username?: string): Promise<AccessToken> {
53
+ const url = new URL(AZURE_BASE_URL);
54
+ addAzureParams(url, tokenAudience, username);
55
+ const response = await get(url, {
56
+ headers: AZURE_HEADERS
57
+ });
58
+ if (response.status !== 200) {
59
+ throw new MongoAzureError(
60
+ `Status code ${response.status} returned from the Azure endpoint. Response body: ${response.body}`
61
+ );
62
+ }
63
+ const result = JSON.parse(response.body);
64
+ return {
65
+ access_token: result.access_token,
66
+ expires_in: Number(result.expires_in)
67
+ };
68
+ }
69
+
70
+ /**
71
+ * Determines if a result returned from the endpoint is valid.
72
+ * This means the result is not nullish, contains the access_token required field
73
+ * and the expires_in required field.
74
+ */
75
+ function isEndpointResultValid(
76
+ token: unknown
77
+ ): token is { access_token: unknown; expires_in: unknown } {
78
+ if (token == null || typeof token !== 'object') return false;
79
+ return (
80
+ 'access_token' in token &&
81
+ typeof token.access_token === 'string' &&
82
+ 'expires_in' in token &&
83
+ typeof token.expires_in === 'number'
84
+ );
85
+ }