Initial Commit

This commit is contained in:
Ben Mosley
2026-05-05 16:07:48 -05:00
commit 0a6e2a2aae
1180 changed files with 200620 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthProvider = exports.AuthContext = void 0;
const error_1 = require("../../error");
/**
* Context used during authentication
* @internal
*/
class AuthContext {
constructor(connection, credentials, options) {
/** If the context is for reauthentication. */
this.reauthenticating = false;
this.connection = connection;
this.credentials = credentials;
this.options = options;
}
}
exports.AuthContext = AuthContext;
/**
* Provider used during authentication.
* @internal
*/
class AuthProvider {
/**
* Prepare the handshake document before the initial handshake.
*
* @param handshakeDoc - The document used for the initial handshake on a connection
* @param authContext - Context for authentication flow
*/
async prepare(handshakeDoc, _authContext) {
return handshakeDoc;
}
/**
* Reauthenticate.
* @param context - The shared auth context.
*/
async reauth(context) {
if (context.reauthenticating) {
throw new error_1.MongoRuntimeError('Reauthentication already in progress.');
}
try {
context.reauthenticating = true;
await this.auth(context);
}
finally {
context.reauthenticating = false;
}
}
}
exports.AuthProvider = AuthProvider;
//# sourceMappingURL=auth_provider.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"auth_provider.js","sourceRoot":"","sources":["../../../src/cmap/auth/auth_provider.ts"],"names":[],"mappings":";;;AACA,uCAAgD;AAKhD;;;GAGG;AACH,MAAa,WAAW;IAetB,YACE,UAAsB,EACtB,WAAyC,EACzC,OAA0B;QAb5B,8CAA8C;QAC9C,qBAAgB,GAAG,KAAK,CAAC;QAcvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAxBD,kCAwBC;AAED;;;GAGG;AACH,MAAsB,YAAY;IAChC;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CACX,YAA+B,EAC/B,YAAyB;QAEzB,OAAO,YAAY,CAAC;IACtB,CAAC;IASD;;;OAGG;IACH,KAAK,CAAC,MAAM,CAAC,OAAoB;QAC/B,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC7B,MAAM,IAAI,yBAAiB,CAAC,uCAAuC,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,CAAC;YACH,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAChC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,gBAAgB,GAAG,KAAK,CAAC;QACnC,CAAC;IACH,CAAC;CACF;AApCD,oCAoCC"}

161
backend/node_modules/mongodb/lib/cmap/auth/aws4.js generated vendored Normal file
View File

@@ -0,0 +1,161 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.aws4Sign = aws4Sign;
const bson_1 = require("../../bson");
/**
* Calculates the SHA-256 hash of a string.
*
* @param str - String to hash.
* @returns Hexadecimal representation of the hash.
*/
const getHexSha256 = async (str) => {
const data = stringToBuffer(str);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashHex = bson_1.ByteUtils.toHex(new Uint8Array(hashBuffer));
return hashHex;
};
/**
* Calculates the HMAC-SHA256 of a string using the provided key.
* @param key - Key to use for HMAC calculation. Can be a string or Uint8Array.
* @param str - String to calculate HMAC for.
* @returns Uint8Array containing the HMAC-SHA256 digest.
*/
const getHmacSha256 = async (key, str) => {
let keyData;
if (typeof key === 'string') {
keyData = stringToBuffer(key);
}
else {
keyData = key;
}
const importedKey = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']);
const strData = stringToBuffer(str);
const signature = await crypto.subtle.sign('HMAC', importedKey, strData);
const digest = new Uint8Array(signature);
return digest;
};
/**
* Converts header values according to AWS requirements,
* From https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html#create-canonical-request
* For values, you must:
- trim any leading or trailing spaces.
- convert sequential spaces to a single space.
* @param value - Header value to convert.
* @returns - Converted header value.
*/
const convertHeaderValue = (value) => {
return value.toString().trim().replace(/\s+/g, ' ');
};
/**
* Returns a Uint8Array representation of a string, encoded in UTF-8.
* @param str - String to convert.
* @returns Uint8Array containing the UTF-8 encoded string.
*/
function stringToBuffer(str) {
const data = new Uint8Array(bson_1.ByteUtils.utf8ByteLength(str));
bson_1.ByteUtils.encodeUTF8Into(data, str, 0);
return data;
}
/**
* This method implements AWS Signature 4 logic for a very specific request format.
* The signing logic is described here: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html
*/
async function aws4Sign(options, credentials) {
/**
* From the spec: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html
*
* Summary of signing steps
* 1. Create a canonical request
* Arrange the contents of your request (host, action, headers, etc.) into a standard canonical format. The canonical request is one of the inputs used to create the string to sign.
* 2. Create a hash of the canonical request
* Hash the canonical request using the same algorithm that you used to create the hash of the payload. The hash of the canonical request is a string of lowercase hexadecimal characters.
* 3. Create a string to sign
* Create a string to sign with the canonical request and extra information such as the algorithm, request date, credential scope, and the hash of the canonical request.
* 4. Derive a signing key
* Use the secret access key to derive the key used to sign the request.
* 5. Calculate the signature
* Perform a keyed hash operation on the string to sign using the derived signing key as the hash key.
* 6. Add the signature to the request
* Add the calculated signature to an HTTP header or to the query string of the request.
*/
// 1: Create a canonical request
// Date The date and time used to sign the request.
const date = options.date;
// RequestDateTime The date and time used in the credential scope. This value is the current UTC time in ISO 8601 format (for example, 20130524T000000Z).
const requestDateTime = date.toISOString().replace(/[:-]|\.\d{3}/g, '');
// RequestDate The date used in the credential scope. This value is the current UTC date in YYYYMMDD format (for example, 20130524).
const requestDate = requestDateTime.substring(0, 8);
// Method The HTTP request method. For us, this is always 'POST'.
const method = options.method;
// CanonicalUri The URI-encoded version of the absolute path component URI, starting with the / that follows the domain name and up to the end of the string
// For our requests, this is always '/'
const canonicalUri = options.path;
// CanonicalQueryString The URI-encoded query string parameters. For our requests, there are no query string parameters, so this is always an empty string.
const canonicalQuerystring = '';
// CanonicalHeaders A list of request headers with their values. Individual header name and value pairs are separated by the newline character ("\n").
// All of our known/expected headers are included here, there are no extra headers.
const headers = new Headers({
'content-length': convertHeaderValue(options.headers['Content-Length']),
'content-type': convertHeaderValue(options.headers['Content-Type']),
host: convertHeaderValue(options.host),
'x-amz-date': convertHeaderValue(requestDateTime),
'x-mongodb-gs2-cb-flag': convertHeaderValue(options.headers['X-MongoDB-GS2-CB-Flag']),
'x-mongodb-server-nonce': convertHeaderValue(options.headers['X-MongoDB-Server-Nonce'])
});
// If session token is provided, include it in the headers
if ('sessionToken' in credentials && credentials.sessionToken) {
headers.append('x-amz-security-token', convertHeaderValue(credentials.sessionToken));
}
// Canonical headers are lowercased and sorted.
const canonicalHeaders = Array.from(headers.entries())
.map(([key, value]) => `${key.toLowerCase()}:${value}`)
.sort()
.join('\n');
const canonicalHeaderNames = Array.from(headers.keys()).map(header => header.toLowerCase());
// SignedHeaders An alphabetically sorted, semicolon-separated list of lowercase request header names.
const signedHeaders = canonicalHeaderNames.sort().join(';');
// HashedPayload A string created using the payload in the body of the HTTP request as input to a hash function. This string uses lowercase hexadecimal characters.
const hashedPayload = await getHexSha256(options.body);
// CanonicalRequest A string that includes the above elements, separated by newline characters.
const canonicalRequest = [
method,
canonicalUri,
canonicalQuerystring,
canonicalHeaders + '\n',
signedHeaders,
hashedPayload
].join('\n');
// 2. Create a hash of the canonical request
// HashedCanonicalRequest A string created by using the canonical request as input to a hash function.
const hashedCanonicalRequest = await getHexSha256(canonicalRequest);
// 3. Create a string to sign
// Algorithm The algorithm used to create the hash of the canonical request. For SigV4, use AWS4-HMAC-SHA256.
const algorithm = 'AWS4-HMAC-SHA256';
// CredentialScope The credential scope, which restricts the resulting signature to the specified Region and service.
// Has the following format: YYYYMMDD/region/service/aws4_request.
const credentialScope = `${requestDate}/${options.region}/${options.service}/aws4_request`;
// StringToSign A string that includes the above elements, separated by newline characters.
const stringToSign = [algorithm, requestDateTime, credentialScope, hashedCanonicalRequest].join('\n');
// 4. Derive a signing key
// To derive a signing key for SigV4, perform a succession of keyed hash operations (HMAC) on the request date, Region, and service, with your AWS secret access key as the key for the initial hashing operation.
const dateKey = await getHmacSha256('AWS4' + credentials.secretAccessKey, requestDate);
const dateRegionKey = await getHmacSha256(dateKey, options.region);
const dateRegionServiceKey = await getHmacSha256(dateRegionKey, options.service);
const signingKey = await getHmacSha256(dateRegionServiceKey, 'aws4_request');
// 5. Calculate the signature
const signatureBuffer = await getHmacSha256(signingKey, stringToSign);
const signature = bson_1.ByteUtils.toHex(signatureBuffer);
// 6. Add the signature to the request
// Calculate the Authorization header
const authorizationHeader = [
'AWS4-HMAC-SHA256 Credential=' + credentials.accessKeyId + '/' + credentialScope,
'SignedHeaders=' + signedHeaders,
'Signature=' + signature
].join(', ');
// Return the calculated headers
return {
Authorization: authorizationHeader,
'X-Amz-Date': requestDateTime
};
}
//# sourceMappingURL=aws4.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"aws4.js","sourceRoot":"","sources":["../../../src/cmap/auth/aws4.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,103 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AWSSDKCredentialProvider = void 0;
const process = require("process");
const deps_1 = require("../../deps");
const error_1 = require("../../error");
/** @internal */
class AWSSDKCredentialProvider {
/**
* Create the SDK credentials provider.
* @param credentialsProvider - The credentials provider.
*/
constructor(credentialsProvider) {
if (credentialsProvider) {
this._provider = credentialsProvider;
}
}
static get awsSDK() {
AWSSDKCredentialProvider._awsSDK ??= (0, deps_1.getAwsCredentialProvider)();
return AWSSDKCredentialProvider._awsSDK;
}
/**
* The AWS SDK caches credentials automatically and handles refresh when the credentials have expired.
* To ensure this occurs, we need to cache the `provider` returned by the AWS sdk and re-use it when fetching credentials.
*/
get provider() {
if ('kModuleError' in AWSSDKCredentialProvider.awsSDK) {
throw AWSSDKCredentialProvider.awsSDK.kModuleError;
}
if (this._provider) {
return this._provider;
}
let { AWS_STS_REGIONAL_ENDPOINTS = '', AWS_REGION = '' } = process.env;
AWS_STS_REGIONAL_ENDPOINTS = AWS_STS_REGIONAL_ENDPOINTS.toLowerCase();
AWS_REGION = AWS_REGION.toLowerCase();
/** The option setting should work only for users who have explicit settings in their environment, the driver should not encode "defaults" */
const awsRegionSettingsExist = AWS_REGION.length !== 0 && AWS_STS_REGIONAL_ENDPOINTS.length !== 0;
/**
* The following regions use the global AWS STS endpoint, sts.amazonaws.com, by default
* https://docs.aws.amazon.com/sdkref/latest/guide/feature-sts-regionalized-endpoints.html
*/
const LEGACY_REGIONS = new Set([
'ap-northeast-1',
'ap-south-1',
'ap-southeast-1',
'ap-southeast-2',
'aws-global',
'ca-central-1',
'eu-central-1',
'eu-north-1',
'eu-west-1',
'eu-west-2',
'eu-west-3',
'sa-east-1',
'us-east-1',
'us-east-2',
'us-west-1',
'us-west-2'
]);
/**
* If AWS_STS_REGIONAL_ENDPOINTS is set to regional, users are opting into the new behavior of respecting the region settings
*
* If AWS_STS_REGIONAL_ENDPOINTS is set to legacy, then "old" regions need to keep using the global setting.
* Technically the SDK gets this wrong, it reaches out to 'sts.us-east-1.amazonaws.com' when it should be 'sts.amazonaws.com'.
* That is not our bug to fix here. We leave that up to the SDK.
*/
const useRegionalSts = AWS_STS_REGIONAL_ENDPOINTS === 'regional' ||
(AWS_STS_REGIONAL_ENDPOINTS === 'legacy' && !LEGACY_REGIONS.has(AWS_REGION));
this._provider =
awsRegionSettingsExist && useRegionalSts
? AWSSDKCredentialProvider.awsSDK.fromNodeProviderChain({
clientConfig: { region: AWS_REGION }
})
: AWSSDKCredentialProvider.awsSDK.fromNodeProviderChain();
return this._provider;
}
async getCredentials() {
/*
* Creates a credential provider that will attempt to find credentials from the
* following sources (listed in order of precedence):
*
* - Environment variables exposed via process.env
* - SSO credentials from token cache
* - Web identity token credentials
* - Shared credentials and config ini files
* - The EC2/ECS Instance Metadata Service
*/
try {
const creds = await this.provider();
return {
AccessKeyId: creds.accessKeyId,
SecretAccessKey: creds.secretAccessKey,
Token: creds.sessionToken,
Expiration: creds.expiration
};
}
catch (error) {
throw new error_1.MongoAWSError(error.message, { cause: error });
}
}
}
exports.AWSSDKCredentialProvider = AWSSDKCredentialProvider;
//# sourceMappingURL=aws_temporary_credentials.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"aws_temporary_credentials.js","sourceRoot":"","sources":["../../../src/cmap/auth/aws_temporary_credentials.ts"],"names":[],"mappings":";;;AAAA,mCAAmC;AAEnC,qCAA2E;AAC3E,uCAA4C;AAoB5C,gBAAgB;AAChB,MAAa,wBAAwB;IAInC;;;OAGG;IACH,YAAY,mBAA2C;QACrD,IAAI,mBAAmB,EAAE,CAAC;YACxB,IAAI,CAAC,SAAS,GAAG,mBAAmB,CAAC;QACvC,CAAC;IACH,CAAC;IAED,MAAM,KAAK,MAAM;QACf,wBAAwB,CAAC,OAAO,KAAK,IAAA,+BAAwB,GAAE,CAAC;QAChE,OAAO,wBAAwB,CAAC,OAAO,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,IAAY,QAAQ;QAClB,IAAI,cAAc,IAAI,wBAAwB,CAAC,MAAM,EAAE,CAAC;YACtD,MAAM,wBAAwB,CAAC,MAAM,CAAC,YAAY,CAAC;QACrD,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC,SAAS,CAAC;QACxB,CAAC;QACD,IAAI,EAAE,0BAA0B,GAAG,EAAE,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;QACvE,0BAA0B,GAAG,0BAA0B,CAAC,WAAW,EAAE,CAAC;QACtE,UAAU,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QAEtC,6IAA6I;QAC7I,MAAM,sBAAsB,GAC1B,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,0BAA0B,CAAC,MAAM,KAAK,CAAC,CAAC;QAErE;;;WAGG;QACH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;YAC7B,gBAAgB;YAChB,YAAY;YACZ,gBAAgB;YAChB,gBAAgB;YAChB,YAAY;YACZ,cAAc;YACd,cAAc;YACd,YAAY;YACZ,WAAW;YACX,WAAW;YACX,WAAW;YACX,WAAW;YACX,WAAW;YACX,WAAW;YACX,WAAW;YACX,WAAW;SACZ,CAAC,CAAC;QACH;;;;;;WAMG;QACH,MAAM,cAAc,GAClB,0BAA0B,KAAK,UAAU;YACzC,CAAC,0BAA0B,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;QAE/E,IAAI,CAAC,SAAS;YACZ,sBAAsB,IAAI,cAAc;gBACtC,CAAC,CAAC,wBAAwB,CAAC,MAAM,CAAC,qBAAqB,CAAC;oBACpD,YAAY,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;iBACrC,CAAC;gBACJ,CAAC,CAAC,wBAAwB,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC;QAE9D,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,cAAc;QAClB;;;;;;;;;WASG;QACH,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,OAAO;gBACL,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,eAAe,EAAE,KAAK,CAAC,eAAe;gBACtC,KAAK,EAAE,KAAK,CAAC,YAAY;gBACzB,UAAU,EAAE,KAAK,CAAC,UAAU;aAC7B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,qBAAa,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;CACF;AAxGD,4DAwGC"}

152
backend/node_modules/mongodb/lib/cmap/auth/gssapi.js generated vendored Normal file
View File

@@ -0,0 +1,152 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GSSAPI = exports.GSSAPICanonicalizationValue = void 0;
exports.performGSSAPICanonicalizeHostName = performGSSAPICanonicalizeHostName;
exports.resolveCname = resolveCname;
const dns = require("dns");
const deps_1 = require("../../deps");
const error_1 = require("../../error");
const utils_1 = require("../../utils");
const auth_provider_1 = require("./auth_provider");
/** @public */
exports.GSSAPICanonicalizationValue = Object.freeze({
on: true,
off: false,
none: 'none',
forward: 'forward',
forwardAndReverse: 'forwardAndReverse'
});
async function externalCommand(connection, command) {
const response = await connection.command((0, utils_1.ns)('$external.$cmd'), command);
return response;
}
let krb;
class GSSAPI extends auth_provider_1.AuthProvider {
async auth(authContext) {
const { connection, credentials } = authContext;
if (credentials == null) {
throw new error_1.MongoMissingCredentialsError('Credentials required for GSSAPI authentication');
}
const { username } = credentials;
const client = await makeKerberosClient(authContext);
const payload = await client.step('');
const saslStartResponse = await externalCommand(connection, saslStart(payload));
const negotiatedPayload = await negotiate(client, 10, saslStartResponse.payload);
const saslContinueResponse = await externalCommand(connection, saslContinue(negotiatedPayload, saslStartResponse.conversationId));
const finalizePayload = await finalize(client, username, saslContinueResponse.payload);
await externalCommand(connection, {
saslContinue: 1,
conversationId: saslContinueResponse.conversationId,
payload: finalizePayload
});
}
}
exports.GSSAPI = GSSAPI;
async function makeKerberosClient({ options: { hostAddress, runtime: { os } }, credentials }) {
if (!hostAddress || typeof hostAddress.host !== 'string' || !credentials) {
throw new error_1.MongoInvalidArgumentError('Connection must have host and port and credentials defined.');
}
loadKrb();
if ('kModuleError' in krb) {
throw krb['kModuleError'];
}
const { initializeClient } = krb;
const { username, password } = credentials;
const mechanismProperties = credentials.mechanismProperties;
const serviceName = mechanismProperties.SERVICE_NAME ?? 'mongodb';
const host = await performGSSAPICanonicalizeHostName(hostAddress.host, mechanismProperties);
const initOptions = {};
if (password != null) {
// TODO(NODE-5139): These do not match the typescript options in initializeClient
Object.assign(initOptions, { user: username, password: password });
}
const spnHost = mechanismProperties.SERVICE_HOST ?? host;
let spn = `${serviceName}${os.platform() === 'win32' ? '/' : '@'}${spnHost}`;
if ('SERVICE_REALM' in mechanismProperties) {
spn = `${spn}@${mechanismProperties.SERVICE_REALM}`;
}
return await initializeClient(spn, initOptions);
}
function saslStart(payload) {
return {
saslStart: 1,
mechanism: 'GSSAPI',
payload,
autoAuthorize: 1
};
}
function saslContinue(payload, conversationId) {
return {
saslContinue: 1,
conversationId,
payload
};
}
async function negotiate(client, retries, payload) {
try {
const response = await client.step(payload);
return response || '';
}
catch (error) {
if (retries === 0) {
// Retries exhausted, raise error
throw error;
}
// Adjust number of retries and call step again
return await negotiate(client, retries - 1, payload);
}
}
async function finalize(client, user, payload) {
// GSS Client Unwrap
const response = await client.unwrap(payload);
return await client.wrap(response || '', { user });
}
async function performGSSAPICanonicalizeHostName(host, mechanismProperties) {
const mode = mechanismProperties.CANONICALIZE_HOST_NAME;
if (!mode || mode === exports.GSSAPICanonicalizationValue.none) {
return host;
}
// If forward and reverse or true
if (mode === exports.GSSAPICanonicalizationValue.on ||
mode === exports.GSSAPICanonicalizationValue.forwardAndReverse) {
// Perform the lookup of the ip address.
const { address } = await dns.promises.lookup(host);
try {
// Perform a reverse ptr lookup on the ip address.
const results = await dns.promises.resolve(address, 'PTR');
// If the ptr did not error but had no results, return the host.
return results.length > 0 ? results[0] : host;
}
catch {
// This can error as ptr records may not exist for all ips. In this case
// fallback to a cname lookup as dns.lookup() does not return the
// cname.
return await resolveCname(host);
}
}
else {
// The case for forward is just to resolve the cname as dns.lookup()
// will not return it.
return await resolveCname(host);
}
}
async function resolveCname(host) {
// Attempt to resolve the host name
try {
const results = await dns.promises.resolve(host, 'CNAME');
// Get the first resolved host id
return results.length > 0 ? results[0] : host;
}
catch {
return host;
}
}
/**
* Load the Kerberos library.
*/
function loadKrb() {
if (!krb) {
krb = (0, deps_1.getKerberos)();
}
}
//# sourceMappingURL=gssapi.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"gssapi.js","sourceRoot":"","sources":["../../../src/cmap/auth/gssapi.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,169 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MongoCredentials = exports.DEFAULT_ALLOWED_HOSTS = void 0;
const error_1 = require("../../error");
const gssapi_1 = require("./gssapi");
const providers_1 = require("./providers");
/**
* @see https://github.com/mongodb/specifications/blob/master/source/auth/auth.md
*/
function getDefaultAuthMechanism(hello) {
if (hello) {
// If hello contains saslSupportedMechs, use scram-sha-256
// if it is available, else scram-sha-1
if (Array.isArray(hello.saslSupportedMechs)) {
return hello.saslSupportedMechs.includes(providers_1.AuthMechanism.MONGODB_SCRAM_SHA256)
? providers_1.AuthMechanism.MONGODB_SCRAM_SHA256
: providers_1.AuthMechanism.MONGODB_SCRAM_SHA1;
}
}
// Default auth mechanism for 4.0 and higher.
return providers_1.AuthMechanism.MONGODB_SCRAM_SHA256;
}
const ALLOWED_ENVIRONMENT_NAMES = [
'test',
'azure',
'gcp',
'k8s'
];
const ALLOWED_HOSTS_ERROR = 'Auth mechanism property ALLOWED_HOSTS must be an array of strings.';
/** @internal */
exports.DEFAULT_ALLOWED_HOSTS = [
'*.mongodb.net',
'*.mongodb-qa.net',
'*.mongodb-dev.net',
'*.mongodbgov.net',
'localhost',
'127.0.0.1',
'::1',
'*.mongo.com'
];
/** Error for when the token audience is missing in the environment. */
const TOKEN_RESOURCE_MISSING_ERROR = 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure or gcp.';
/**
* A representation of the credentials used by MongoDB
* @public
*/
class MongoCredentials {
constructor(options) {
this.username = options.username ?? '';
this.password = options.password;
this.source = options.source;
if (!this.source && options.db) {
this.source = options.db;
}
this.mechanism = options.mechanism || providers_1.AuthMechanism.MONGODB_DEFAULT;
this.mechanismProperties = options.mechanismProperties || {};
if (this.mechanism === providers_1.AuthMechanism.MONGODB_OIDC && !this.mechanismProperties.ALLOWED_HOSTS) {
this.mechanismProperties = {
...this.mechanismProperties,
ALLOWED_HOSTS: exports.DEFAULT_ALLOWED_HOSTS
};
}
Object.freeze(this.mechanismProperties);
Object.freeze(this);
}
/** Determines if two MongoCredentials objects are equivalent */
equals(other) {
return (this.mechanism === other.mechanism &&
this.username === other.username &&
this.password === other.password &&
this.source === other.source);
}
/**
* If the authentication mechanism is set to "default", resolves the authMechanism
* based on the server version and server supported sasl mechanisms.
*
* @param hello - A hello response from the server
*/
resolveAuthMechanism(hello) {
// If the mechanism is not "default", then it does not need to be resolved
if (this.mechanism.match(/DEFAULT/i)) {
return new MongoCredentials({
username: this.username,
password: this.password,
source: this.source,
mechanism: getDefaultAuthMechanism(hello),
mechanismProperties: this.mechanismProperties
});
}
return this;
}
validate() {
if ((this.mechanism === providers_1.AuthMechanism.MONGODB_GSSAPI ||
this.mechanism === providers_1.AuthMechanism.MONGODB_PLAIN ||
this.mechanism === providers_1.AuthMechanism.MONGODB_SCRAM_SHA1 ||
this.mechanism === providers_1.AuthMechanism.MONGODB_SCRAM_SHA256) &&
!this.username) {
throw new error_1.MongoMissingCredentialsError(`Username required for mechanism '${this.mechanism}'`);
}
if (this.mechanism === providers_1.AuthMechanism.MONGODB_OIDC) {
if (this.username &&
this.mechanismProperties.ENVIRONMENT &&
this.mechanismProperties.ENVIRONMENT !== 'azure') {
throw new error_1.MongoInvalidArgumentError(`username and ENVIRONMENT '${this.mechanismProperties.ENVIRONMENT}' may not be used together for mechanism '${this.mechanism}'.`);
}
if (this.username && this.password) {
throw new error_1.MongoInvalidArgumentError(`No password is allowed in ENVIRONMENT '${this.mechanismProperties.ENVIRONMENT}' for '${this.mechanism}'.`);
}
if ((this.mechanismProperties.ENVIRONMENT === 'azure' ||
this.mechanismProperties.ENVIRONMENT === 'gcp') &&
!this.mechanismProperties.TOKEN_RESOURCE) {
throw new error_1.MongoInvalidArgumentError(TOKEN_RESOURCE_MISSING_ERROR);
}
if (this.mechanismProperties.ENVIRONMENT &&
!ALLOWED_ENVIRONMENT_NAMES.includes(this.mechanismProperties.ENVIRONMENT)) {
throw new error_1.MongoInvalidArgumentError(`Currently only a ENVIRONMENT in ${ALLOWED_ENVIRONMENT_NAMES.join(',')} is supported for mechanism '${this.mechanism}'.`);
}
if (!this.mechanismProperties.ENVIRONMENT &&
!this.mechanismProperties.OIDC_CALLBACK &&
!this.mechanismProperties.OIDC_HUMAN_CALLBACK) {
throw new error_1.MongoInvalidArgumentError(`Either a ENVIRONMENT, OIDC_CALLBACK, or OIDC_HUMAN_CALLBACK must be specified for mechanism '${this.mechanism}'.`);
}
if (this.mechanismProperties.ALLOWED_HOSTS) {
const hosts = this.mechanismProperties.ALLOWED_HOSTS;
if (!Array.isArray(hosts)) {
throw new error_1.MongoInvalidArgumentError(ALLOWED_HOSTS_ERROR);
}
for (const host of hosts) {
if (typeof host !== 'string') {
throw new error_1.MongoInvalidArgumentError(ALLOWED_HOSTS_ERROR);
}
}
}
}
if (providers_1.AUTH_MECHS_AUTH_SRC_EXTERNAL.has(this.mechanism)) {
if (this.source != null && this.source !== '$external') {
// TODO(NODE-3485): Replace this with a MongoAuthValidationError
throw new error_1.MongoAPIError(`Invalid source '${this.source}' for mechanism '${this.mechanism}' specified.`);
}
}
if (this.mechanism === providers_1.AuthMechanism.MONGODB_PLAIN && this.source == null) {
// TODO(NODE-3485): Replace this with a MongoAuthValidationError
throw new error_1.MongoAPIError('PLAIN Authentication Mechanism needs an auth source');
}
if (this.mechanism === providers_1.AuthMechanism.MONGODB_X509 && this.password != null) {
if (this.password === '') {
Reflect.set(this, 'password', undefined);
return;
}
// TODO(NODE-3485): Replace this with a MongoAuthValidationError
throw new error_1.MongoAPIError(`Password not allowed for mechanism MONGODB-X509`);
}
const canonicalization = this.mechanismProperties.CANONICALIZE_HOST_NAME ?? false;
if (!Object.values(gssapi_1.GSSAPICanonicalizationValue).includes(canonicalization)) {
throw new error_1.MongoAPIError(`Invalid CANONICALIZE_HOST_NAME value: ${canonicalization}`);
}
}
static merge(creds, options) {
return new MongoCredentials({
username: options.username ?? creds?.username ?? '',
password: options.password ?? creds?.password ?? '',
mechanism: options.mechanism ?? creds?.mechanism ?? providers_1.AuthMechanism.MONGODB_DEFAULT,
mechanismProperties: options.mechanismProperties ?? creds?.mechanismProperties ?? {},
source: options.source ?? options.db ?? creds?.source ?? 'admin'
});
}
}
exports.MongoCredentials = MongoCredentials;
//# sourceMappingURL=mongo_credentials.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,129 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MongoDBAWS = void 0;
const bson_1 = require("../../bson");
const BSON = require("../../bson");
const error_1 = require("../../error");
const utils_1 = require("../../utils");
const auth_provider_1 = require("./auth_provider");
const aws_temporary_credentials_1 = require("./aws_temporary_credentials");
const aws4_1 = require("./aws4");
const mongo_credentials_1 = require("./mongo_credentials");
const providers_1 = require("./providers");
const ASCII_N = 110;
const bsonOptions = {
useBigInt64: false,
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
bsonRegExp: false
};
class MongoDBAWS extends auth_provider_1.AuthProvider {
constructor(credentialProvider) {
super();
this.credentialFetcher = new aws_temporary_credentials_1.AWSSDKCredentialProvider(credentialProvider);
}
async auth(authContext) {
const { connection } = authContext;
if (!authContext.credentials) {
throw new error_1.MongoMissingCredentialsError('AuthContext must provide credentials.');
}
if ((0, utils_1.maxWireVersion)(connection) < 9) {
throw new error_1.MongoCompatibilityError('MONGODB-AWS authentication requires MongoDB version 4.4 or later');
}
authContext.credentials = await makeTempCredentials(authContext.credentials, this.credentialFetcher);
const { credentials } = authContext;
const accessKeyId = credentials.username;
const secretAccessKey = credentials.password;
// Allow the user to specify an AWS session token for authentication with temporary credentials.
const sessionToken = credentials.mechanismProperties.AWS_SESSION_TOKEN;
// If all three defined, include sessionToken, else only include username and pass
const awsCredentials = sessionToken
? { accessKeyId, secretAccessKey, sessionToken }
: { accessKeyId, secretAccessKey };
const db = credentials.source;
const nonce = await (0, utils_1.randomBytes)(32);
// All messages between MongoDB clients and servers are sent as BSON objects
// in the payload field of saslStart and saslContinue.
const saslStart = {
saslStart: 1,
mechanism: 'MONGODB-AWS',
payload: BSON.serialize({ r: nonce, p: ASCII_N }, bsonOptions)
};
const saslStartResponse = await connection.command((0, utils_1.ns)(`${db}.$cmd`), saslStart, undefined);
const serverResponse = BSON.deserialize(saslStartResponse.payload.buffer, bsonOptions);
const host = serverResponse.h;
const serverNonce = serverResponse.s.buffer;
if (serverNonce.length !== 64) {
// TODO(NODE-3483)
throw new error_1.MongoRuntimeError(`Invalid server nonce length ${serverNonce.length}, expected 64`);
}
if (!bson_1.ByteUtils.equals(serverNonce.subarray(0, nonce.byteLength), nonce)) {
// throw because the serverNonce's leading 32 bytes must equal the client nonce's 32 bytes
// https://github.com/mongodb/specifications/blob/master/source/auth/auth.md#conversation-5
// TODO(NODE-3483)
throw new error_1.MongoRuntimeError('Server nonce does not begin with client nonce');
}
if (host.length < 1 || host.length > 255 || host.indexOf('..') !== -1) {
// TODO(NODE-3483)
throw new error_1.MongoRuntimeError(`Server returned an invalid host: "${host}"`);
}
const body = 'Action=GetCallerIdentity&Version=2011-06-15';
const headers = await (0, aws4_1.aws4Sign)({
method: 'POST',
host,
region: deriveRegion(serverResponse.h),
service: 'sts',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': body.length,
'X-MongoDB-Server-Nonce': bson_1.ByteUtils.toBase64(serverNonce),
'X-MongoDB-GS2-CB-Flag': 'n'
},
path: '/',
body,
date: new Date()
}, awsCredentials);
const payload = {
a: headers.Authorization,
d: headers['X-Amz-Date']
};
if (sessionToken) {
payload.t = sessionToken;
}
const saslContinue = {
saslContinue: 1,
conversationId: saslStartResponse.conversationId,
payload: BSON.serialize(payload, bsonOptions)
};
await connection.command((0, utils_1.ns)(`${db}.$cmd`), saslContinue, undefined);
}
}
exports.MongoDBAWS = MongoDBAWS;
async function makeTempCredentials(credentials, awsCredentialFetcher) {
function makeMongoCredentialsFromAWSTemp(creds) {
// The AWS session token (creds.Token) may or may not be set.
if (!creds.AccessKeyId || !creds.SecretAccessKey) {
throw new error_1.MongoMissingCredentialsError('Could not obtain temporary MONGODB-AWS credentials');
}
return new mongo_credentials_1.MongoCredentials({
username: creds.AccessKeyId,
password: creds.SecretAccessKey,
source: credentials.source,
mechanism: providers_1.AuthMechanism.MONGODB_AWS,
mechanismProperties: {
AWS_SESSION_TOKEN: creds.Token
}
});
}
const temporaryCredentials = await awsCredentialFetcher.getCredentials();
return makeMongoCredentialsFromAWSTemp(temporaryCredentials);
}
function deriveRegion(host) {
const parts = host.split('.');
if (parts.length === 1 || parts[1] === 'amazonaws') {
return 'us-east-1';
}
return parts[1];
}
//# sourceMappingURL=mongodb_aws.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mongodb_aws.js","sourceRoot":"","sources":["../../../src/cmap/auth/mongodb_aws.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,73 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MongoDBOIDC = exports.OIDC_WORKFLOWS = exports.OIDC_VERSION = void 0;
const error_1 = require("../../error");
const auth_provider_1 = require("./auth_provider");
const automated_callback_workflow_1 = require("./mongodb_oidc/automated_callback_workflow");
const azure_machine_workflow_1 = require("./mongodb_oidc/azure_machine_workflow");
const gcp_machine_workflow_1 = require("./mongodb_oidc/gcp_machine_workflow");
const k8s_machine_workflow_1 = require("./mongodb_oidc/k8s_machine_workflow");
const token_cache_1 = require("./mongodb_oidc/token_cache");
const token_machine_workflow_1 = require("./mongodb_oidc/token_machine_workflow");
/** Error when credentials are missing. */
const MISSING_CREDENTIALS_ERROR = 'AuthContext must provide credentials.';
/** The current version of OIDC implementation. */
exports.OIDC_VERSION = 1;
/** @internal */
exports.OIDC_WORKFLOWS = new Map();
exports.OIDC_WORKFLOWS.set('test', () => new automated_callback_workflow_1.AutomatedCallbackWorkflow(new token_cache_1.TokenCache(), token_machine_workflow_1.tokenMachineCallback));
exports.OIDC_WORKFLOWS.set('azure', () => new automated_callback_workflow_1.AutomatedCallbackWorkflow(new token_cache_1.TokenCache(), azure_machine_workflow_1.azureCallback));
exports.OIDC_WORKFLOWS.set('gcp', () => new automated_callback_workflow_1.AutomatedCallbackWorkflow(new token_cache_1.TokenCache(), gcp_machine_workflow_1.gcpCallback));
exports.OIDC_WORKFLOWS.set('k8s', () => new automated_callback_workflow_1.AutomatedCallbackWorkflow(new token_cache_1.TokenCache(), k8s_machine_workflow_1.k8sCallback));
/**
* OIDC auth provider.
*/
class MongoDBOIDC extends auth_provider_1.AuthProvider {
/**
* Instantiate the auth provider.
*/
constructor(workflow) {
super();
if (!workflow) {
throw new error_1.MongoInvalidArgumentError('No workflow provided to the OIDC auth provider.');
}
this.workflow = workflow;
}
/**
* Authenticate using OIDC
*/
async auth(authContext) {
const { connection, reauthenticating, response } = authContext;
if (response?.speculativeAuthenticate?.done && !reauthenticating) {
return;
}
const credentials = getCredentials(authContext);
if (reauthenticating) {
await this.workflow.reauthenticate(connection, credentials);
}
else {
await this.workflow.execute(connection, credentials, response);
}
}
/**
* Add the speculative auth for the initial handshake.
*/
async prepare(handshakeDoc, authContext) {
const { connection } = authContext;
const credentials = getCredentials(authContext);
const result = await this.workflow.speculativeAuth(connection, credentials);
return { ...handshakeDoc, ...result };
}
}
exports.MongoDBOIDC = MongoDBOIDC;
/**
* Get credentials from the auth context, throwing if they do not exist.
*/
function getCredentials(authContext) {
const { credentials } = authContext;
if (!credentials) {
throw new error_1.MongoMissingCredentialsError(MISSING_CREDENTIALS_ERROR);
}
return credentials;
}
//# sourceMappingURL=mongodb_oidc.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mongodb_oidc.js","sourceRoot":"","sources":["../../../src/cmap/auth/mongodb_oidc.ts"],"names":[],"mappings":";;;AACA,uCAAsF;AAGtF,mDAAiE;AAEjE,4FAAuF;AACvF,kFAAsE;AACtE,8EAAkE;AAClE,8EAAkE;AAClE,4DAAwD;AACxD,kFAA6F;AAE7F,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,6CAAY,CAAC,CAAC,CAAC;AAChG,sBAAc,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,uDAAyB,CAAC,IAAI,wBAAU,EAAE,EAAE,sCAAa,CAAC,CAAC,CAAC;AAClG,sBAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,uDAAyB,CAAC,IAAI,wBAAU,EAAE,EAAE,kCAAW,CAAC,CAAC,CAAC;AAC9F,sBAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,uDAAyB,CAAC,IAAI,wBAAU,EAAE,EAAE,kCAAW,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"}

View File

@@ -0,0 +1,84 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutomatedCallbackWorkflow = void 0;
const error_1 = require("../../../error");
const timeout_1 = require("../../../timeout");
const mongodb_oidc_1 = require("../mongodb_oidc");
const callback_workflow_1 = require("./callback_workflow");
/**
* Class implementing behaviour for the non human callback workflow.
* @internal
*/
class AutomatedCallbackWorkflow extends callback_workflow_1.CallbackWorkflow {
/**
* Instantiate the human callback workflow.
*/
constructor(cache, callback) {
super(cache, callback);
}
/**
* Execute the OIDC callback workflow.
*/
async execute(connection, credentials) {
// If there is a cached access token, try to authenticate with it. If
// authentication fails with an Authentication error (18),
// invalidate the access token, fetch a new access token, and try
// to authenticate again.
// If the server fails for any other reason, do not clear the cache.
if (this.cache.hasAccessToken) {
const token = this.cache.getAccessToken();
if (!connection.accessToken) {
connection.accessToken = token;
}
try {
return await this.finishAuthentication(connection, credentials, token);
}
catch (error) {
if (error instanceof error_1.MongoError &&
error.code === error_1.MONGODB_ERROR_CODES.AuthenticationFailed) {
this.cache.removeAccessToken();
return await this.execute(connection, credentials);
}
else {
throw error;
}
}
}
const response = await this.fetchAccessToken(credentials);
this.cache.put(response);
connection.accessToken = response.accessToken;
await this.finishAuthentication(connection, credentials, response.accessToken);
}
/**
* Fetches the access token using the callback.
*/
async fetchAccessToken(credentials) {
const controller = new AbortController();
const params = {
timeoutContext: controller.signal,
version: mongodb_oidc_1.OIDC_VERSION
};
if (credentials.username) {
params.username = credentials.username;
}
if (credentials.mechanismProperties.TOKEN_RESOURCE) {
params.tokenAudience = credentials.mechanismProperties.TOKEN_RESOURCE;
}
const timeout = timeout_1.Timeout.expires(callback_workflow_1.AUTOMATED_TIMEOUT_MS);
try {
return await Promise.race([this.executeAndValidateCallback(params), timeout]);
}
catch (error) {
if (timeout_1.TimeoutError.is(error)) {
controller.abort();
throw new error_1.MongoOIDCError(`OIDC callback timed out after ${callback_workflow_1.AUTOMATED_TIMEOUT_MS}ms.`);
}
throw error;
}
finally {
timeout.clear();
}
}
}
exports.AutomatedCallbackWorkflow = AutomatedCallbackWorkflow;
//# sourceMappingURL=automated_callback_workflow.js.map

View File

@@ -0,0 +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"}

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.azureCallback = void 0;
const azure_1 = require("../../../client-side-encryption/providers/azure");
const error_1 = require("../../../error");
const utils_1 = require("../../../utils");
/** Azure request headers. */
const AZURE_HEADERS = Object.freeze({ Metadata: 'true', Accept: 'application/json' });
/** Invalid endpoint result error. */
const ENDPOINT_RESULT_ERROR = 'Azure endpoint did not return a value with only access_token and expires_in properties';
/** Error for when the token audience is missing in the environment. */
const TOKEN_RESOURCE_MISSING_ERROR = 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure.';
/**
* The callback function to be used in the automated callback workflow.
* @param params - The OIDC callback parameters.
* @returns The OIDC response.
*/
const azureCallback = async (params) => {
const tokenAudience = params.tokenAudience;
const username = params.username;
if (!tokenAudience) {
throw new error_1.MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
}
const response = await getAzureTokenData(tokenAudience, username);
if (!isEndpointResultValid(response)) {
throw new error_1.MongoAzureError(ENDPOINT_RESULT_ERROR);
}
return response;
};
exports.azureCallback = azureCallback;
/**
* Hit the Azure endpoint to get the token data.
*/
async function getAzureTokenData(tokenAudience, username) {
const url = new URL(azure_1.AZURE_BASE_URL);
(0, azure_1.addAzureParams)(url, tokenAudience, username);
const response = await (0, utils_1.get)(url, {
headers: AZURE_HEADERS
});
if (response.status !== 200) {
throw new error_1.MongoAzureError(`Status code ${response.status} returned from the Azure endpoint. Response body: ${response.body}`);
}
const result = JSON.parse(response.body);
return {
accessToken: result.access_token,
expiresInSeconds: Number(result.expires_in)
};
}
/**
* Determines if a result returned from the endpoint is valid.
* This means the result is not nullish, contains the access_token required field
* and the expires_in required field.
*/
function isEndpointResultValid(token) {
if (token == null || typeof token !== 'object')
return false;
return ('accessToken' in token &&
typeof token.accessToken === 'string' &&
'expiresInSeconds' in token &&
typeof token.expiresInSeconds === 'number');
}
//# sourceMappingURL=azure_machine_workflow.js.map

View File

@@ -0,0 +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,aAAa,GAAyB,KAAK,EACtD,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,aAAa,iBAaxB;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"}

View File

@@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CallbackWorkflow = exports.AUTOMATED_TIMEOUT_MS = exports.HUMAN_TIMEOUT_MS = void 0;
const promises_1 = require("timers/promises");
const error_1 = require("../../../error");
const utils_1 = require("../../../utils");
const command_builders_1 = require("./command_builders");
/** 5 minutes in milliseconds */
exports.HUMAN_TIMEOUT_MS = 300000;
/** 1 minute in milliseconds */
exports.AUTOMATED_TIMEOUT_MS = 60000;
/** Properties allowed on results of callbacks. */
const RESULT_PROPERTIES = ['accessToken', 'expiresInSeconds', 'refreshToken'];
/** Error message when the callback result is invalid. */
const CALLBACK_RESULT_ERROR = 'User provided OIDC callbacks must return a valid object with an accessToken.';
/** The time to throttle callback calls. */
const THROTTLE_MS = 100;
/**
* OIDC implementation of a callback based workflow.
* @internal
*/
class CallbackWorkflow {
/**
* Instantiate the callback workflow.
*/
constructor(cache, callback) {
this.cache = cache;
this.callback = this.withLock(callback);
this.lastExecutionTime = Date.now() - THROTTLE_MS;
}
/**
* Get the document to add for speculative authentication. This also needs
* to add a db field from the credentials source.
*/
async speculativeAuth(connection, credentials) {
// Check if the Client Cache has an access token.
// If it does, cache the access token in the Connection Cache and send a JwtStepRequest
// with the cached access token in the speculative authentication SASL payload.
if (this.cache.hasAccessToken) {
const accessToken = this.cache.getAccessToken();
connection.accessToken = accessToken;
const document = (0, command_builders_1.finishCommandDocument)(accessToken);
document.db = credentials.source;
return { speculativeAuthenticate: document };
}
return {};
}
/**
* Reauthenticate the callback workflow. For this we invalidated the access token
* in the cache and run the authentication steps again. No initial handshake needs
* to be sent.
*/
async reauthenticate(connection, credentials) {
if (this.cache.hasAccessToken) {
// Reauthentication implies the token has expired.
if (connection.accessToken === this.cache.getAccessToken()) {
// If connection's access token is the same as the cache's, remove
// the token from the cache and connection.
this.cache.removeAccessToken();
delete connection.accessToken;
}
else {
// If the connection's access token is different from the cache's, set
// the cache's token on the connection and do not remove from the
// cache.
connection.accessToken = this.cache.getAccessToken();
}
}
await this.execute(connection, credentials);
}
/**
* Starts the callback authentication process. If there is a speculative
* authentication document from the initial handshake, then we will use that
* value to get the issuer, otherwise we will send the saslStart command.
*/
async startAuthentication(connection, credentials, response) {
let result;
if (response?.speculativeAuthenticate) {
result = response.speculativeAuthenticate;
}
else {
result = await connection.command((0, utils_1.ns)(credentials.source), (0, command_builders_1.startCommandDocument)(credentials), undefined);
}
return result;
}
/**
* Finishes the callback authentication process.
*/
async finishAuthentication(connection, credentials, token, conversationId) {
await connection.command((0, utils_1.ns)(credentials.source), (0, command_builders_1.finishCommandDocument)(token, conversationId), undefined);
}
/**
* Executes the callback and validates the output.
*/
async executeAndValidateCallback(params) {
const result = await this.callback(params);
// Validate that the result returned by the callback is acceptable. If it is not
// we must clear the token result from the cache.
if (isCallbackResultInvalid(result)) {
throw new error_1.MongoMissingCredentialsError(CALLBACK_RESULT_ERROR);
}
return result;
}
/**
* Ensure the callback is only executed one at a time and throttles the calls
* to every 100ms.
*/
withLock(callback) {
let lock = Promise.resolve();
return async (params) => {
// We do this to ensure that we would never return the result of the
// previous lock, only the current callback's value would get returned.
await lock;
lock = lock
.catch(() => null)
.then(async () => {
const difference = Date.now() - this.lastExecutionTime;
if (difference <= THROTTLE_MS) {
await (0, promises_1.setTimeout)(THROTTLE_MS - difference, { signal: params.timeoutContext });
}
this.lastExecutionTime = Date.now();
return await callback(params);
});
return await lock;
};
}
}
exports.CallbackWorkflow = CallbackWorkflow;
/**
* Determines if a result returned from a request or refresh callback
* function is invalid. This means the result is nullish, doesn't contain
* the accessToken required field, and does not contain extra fields.
*/
function isCallbackResultInvalid(tokenResult) {
if (tokenResult == null || typeof tokenResult !== 'object')
return true;
if (!('accessToken' in tokenResult))
return true;
return !Object.getOwnPropertyNames(tokenResult).every(prop => RESULT_PROPERTIES.includes(prop));
}
//# sourceMappingURL=callback_workflow.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"callback_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/callback_workflow.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.finishCommandDocument = finishCommandDocument;
exports.startCommandDocument = startCommandDocument;
const bson_1 = require("../../../bson");
const providers_1 = require("../providers");
/**
* Generate the finishing command document for authentication. Will be a
* saslStart or saslContinue depending on the presence of a conversation id.
*/
function finishCommandDocument(token, conversationId) {
if (conversationId != null) {
return {
saslContinue: 1,
conversationId: conversationId,
payload: new bson_1.Binary(bson_1.BSON.serialize({ jwt: token }))
};
}
// saslContinue requires a conversationId in the command to be valid so in this
// case the server allows "step two" to actually be a saslStart with the token
// as the jwt since the use of the cached value has no correlating conversating
// on the particular connection.
return {
saslStart: 1,
mechanism: providers_1.AuthMechanism.MONGODB_OIDC,
payload: new bson_1.Binary(bson_1.BSON.serialize({ jwt: token }))
};
}
/**
* Generate the saslStart command document.
*/
function startCommandDocument(credentials) {
const payload = {};
if (credentials.username) {
payload.n = credentials.username;
}
return {
saslStart: 1,
autoAuthorize: 1,
mechanism: providers_1.AuthMechanism.MONGODB_OIDC,
payload: new bson_1.Binary(bson_1.BSON.serialize(payload))
};
}
//# sourceMappingURL=command_builders.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"command_builders.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/command_builders.ts"],"names":[],"mappings":";;AAmBA,sDAiBC;AAKD,oDAWC;AApDD,wCAA4D;AAE5D,4CAA6C;AAa7C;;;GAGG;AACH,SAAgB,qBAAqB,CAAC,KAAa,EAAE,cAAuB;IAC1E,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;QAC3B,OAAO;YACL,YAAY,EAAE,CAAC;YACf,cAAc,EAAE,cAAc;YAC9B,OAAO,EAAE,IAAI,aAAM,CAAC,WAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;SACpD,CAAC;IACJ,CAAC;IACD,+EAA+E;IAC/E,8EAA8E;IAC9E,+EAA+E;IAC/E,gCAAgC;IAChC,OAAO;QACL,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,yBAAa,CAAC,YAAY;QACrC,OAAO,EAAE,IAAI,aAAM,CAAC,WAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;KACpD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAAC,WAA6B;IAChE,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC;IACnC,CAAC;IACD,OAAO;QACL,SAAS,EAAE,CAAC;QACZ,aAAa,EAAE,CAAC;QAChB,SAAS,EAAE,yBAAa,CAAC,YAAY;QACrC,OAAO,EAAE,IAAI,aAAM,CAAC,WAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;KAC7C,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.gcpCallback = void 0;
const error_1 = require("../../../error");
const utils_1 = require("../../../utils");
/** GCP base URL. */
const GCP_BASE_URL = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity';
/** GCP request headers. */
const GCP_HEADERS = Object.freeze({ 'Metadata-Flavor': 'Google' });
/** Error for when the token audience is missing in the environment. */
const TOKEN_RESOURCE_MISSING_ERROR = 'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is gcp.';
/**
* The callback function to be used in the automated callback workflow.
* @param params - The OIDC callback parameters.
* @returns The OIDC response.
*/
const gcpCallback = async (params) => {
const tokenAudience = params.tokenAudience;
if (!tokenAudience) {
throw new error_1.MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
}
return await getGcpTokenData(tokenAudience);
};
exports.gcpCallback = gcpCallback;
/**
* Hit the GCP endpoint to get the token data.
*/
async function getGcpTokenData(tokenAudience) {
const url = new URL(GCP_BASE_URL);
url.searchParams.append('audience', tokenAudience);
const response = await (0, utils_1.get)(url, {
headers: GCP_HEADERS
});
if (response.status !== 200) {
throw new error_1.MongoGCPError(`Status code ${response.status} returned from the GCP endpoint. Response body: ${response.body}`);
}
return { accessToken: response.body };
}
//# sourceMappingURL=gcp_machine_workflow.js.map

View File

@@ -0,0 +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,WAAW,GAAyB,KAAK,EACpD,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,WAAW,eAQtB;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"}

View File

@@ -0,0 +1,122 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HumanCallbackWorkflow = void 0;
const bson_1 = require("../../../bson");
const error_1 = require("../../../error");
const timeout_1 = require("../../../timeout");
const mongodb_oidc_1 = require("../mongodb_oidc");
const callback_workflow_1 = require("./callback_workflow");
/**
* Class implementing behaviour for the non human callback workflow.
* @internal
*/
class HumanCallbackWorkflow extends callback_workflow_1.CallbackWorkflow {
/**
* Instantiate the human callback workflow.
*/
constructor(cache, callback) {
super(cache, callback);
}
/**
* Execute the OIDC human callback workflow.
*/
async execute(connection, credentials) {
// Check if the Client Cache has an access token.
// If it does, cache the access token in the Connection Cache and perform a One-Step SASL conversation
// using the access token. If the server returns an Authentication error (18),
// invalidate the access token token from the Client Cache, clear the Connection Cache,
// and restart the authentication flow. Raise any other errors to the user. On success, exit the algorithm.
if (this.cache.hasAccessToken) {
const token = this.cache.getAccessToken();
connection.accessToken = token;
try {
return await this.finishAuthentication(connection, credentials, token);
}
catch (error) {
if (error instanceof error_1.MongoError &&
error.code === error_1.MONGODB_ERROR_CODES.AuthenticationFailed) {
this.cache.removeAccessToken();
delete connection.accessToken;
return await this.execute(connection, credentials);
}
else {
throw error;
}
}
}
// Check if the Client Cache has a refresh token.
// If it does, call the OIDC Human Callback with the cached refresh token and IdpInfo to get a
// new access token. Cache the new access token in the Client Cache and Connection Cache.
// Perform a One-Step SASL conversation using the new access token. If the the server returns
// an Authentication error (18), clear the refresh token, invalidate the access token from the
// Client Cache, clear the Connection Cache, and restart the authentication flow. Raise any other
// errors to the user. On success, exit the algorithm.
if (this.cache.hasRefreshToken) {
const refreshToken = this.cache.getRefreshToken();
const result = await this.fetchAccessToken(this.cache.getIdpInfo(), credentials, refreshToken);
this.cache.put(result);
connection.accessToken = result.accessToken;
try {
return await this.finishAuthentication(connection, credentials, result.accessToken);
}
catch (error) {
if (error instanceof error_1.MongoError &&
error.code === error_1.MONGODB_ERROR_CODES.AuthenticationFailed) {
this.cache.removeRefreshToken();
delete connection.accessToken;
return await this.execute(connection, credentials);
}
else {
throw error;
}
}
}
// Start a new Two-Step SASL conversation.
// Run a PrincipalStepRequest to get the IdpInfo.
// Call the OIDC Human Callback with the new IdpInfo to get a new access token and optional refresh
// token. Drivers MUST NOT pass a cached refresh token to the callback when performing
// a new Two-Step conversation. Cache the new IdpInfo and refresh token in the Client Cache and the
// new access token in the Client Cache and Connection Cache.
// Attempt to authenticate using a JwtStepRequest with the new access token. Raise any errors to the user.
const startResponse = await this.startAuthentication(connection, credentials);
const conversationId = startResponse.conversationId;
const idpInfo = bson_1.BSON.deserialize(startResponse.payload.buffer);
const callbackResponse = await this.fetchAccessToken(idpInfo, credentials);
this.cache.put(callbackResponse, idpInfo);
connection.accessToken = callbackResponse.accessToken;
return await this.finishAuthentication(connection, credentials, callbackResponse.accessToken, conversationId);
}
/**
* Fetches an access token using the callback.
*/
async fetchAccessToken(idpInfo, credentials, refreshToken) {
const controller = new AbortController();
const params = {
timeoutContext: controller.signal,
version: mongodb_oidc_1.OIDC_VERSION,
idpInfo: idpInfo
};
if (credentials.username) {
params.username = credentials.username;
}
if (refreshToken) {
params.refreshToken = refreshToken;
}
const timeout = timeout_1.Timeout.expires(callback_workflow_1.HUMAN_TIMEOUT_MS);
try {
return await Promise.race([this.executeAndValidateCallback(params), timeout]);
}
catch (error) {
if (timeout_1.TimeoutError.is(error)) {
controller.abort();
throw new error_1.MongoOIDCError(`OIDC callback timed out after ${callback_workflow_1.HUMAN_TIMEOUT_MS}ms.`);
}
throw error;
}
finally {
timeout.clear();
}
}
}
exports.HumanCallbackWorkflow = HumanCallbackWorkflow;
//# sourceMappingURL=human_callback_workflow.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"human_callback_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/human_callback_workflow.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.k8sCallback = void 0;
const promises_1 = require("fs/promises");
const process = require("process");
/** The fallback file name */
const FALLBACK_FILENAME = '/var/run/secrets/kubernetes.io/serviceaccount/token';
/** The azure environment variable for the file name. */
const AZURE_FILENAME = 'AZURE_FEDERATED_TOKEN_FILE';
/** The AWS environment variable for the file name. */
const AWS_FILENAME = 'AWS_WEB_IDENTITY_TOKEN_FILE';
/**
* The callback function to be used in the automated callback workflow.
* @param params - The OIDC callback parameters.
* @returns The OIDC response.
*/
const k8sCallback = async () => {
let filename;
if (process.env[AZURE_FILENAME]) {
filename = process.env[AZURE_FILENAME];
}
else if (process.env[AWS_FILENAME]) {
filename = process.env[AWS_FILENAME];
}
else {
filename = FALLBACK_FILENAME;
}
const token = await (0, promises_1.readFile)(filename, 'utf8');
return { accessToken: token };
};
exports.k8sCallback = k8sCallback;
//# sourceMappingURL=k8s_machine_workflow.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"k8s_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,0CAAuC;AACvC,mCAAmC;AAInC,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,WAAW,GAAyB,KAAK,IAA2B,EAAE;IACjF,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,WAAW,eAWtB"}

View File

@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TokenCache = void 0;
const error_1 = require("../../../error");
class MongoOIDCError extends error_1.MongoDriverError {
}
/** @internal */
class TokenCache {
get hasAccessToken() {
return !!this.accessToken;
}
get hasRefreshToken() {
return !!this.refreshToken;
}
get hasIdpInfo() {
return !!this.idpInfo;
}
getAccessToken() {
if (!this.accessToken) {
throw new MongoOIDCError('Attempted to get an access token when none exists.');
}
return this.accessToken;
}
getRefreshToken() {
if (!this.refreshToken) {
throw new MongoOIDCError('Attempted to get a refresh token when none exists.');
}
return this.refreshToken;
}
getIdpInfo() {
if (!this.idpInfo) {
throw new MongoOIDCError('Attempted to get IDP information when none exists.');
}
return this.idpInfo;
}
put(response, idpInfo) {
this.accessToken = response.accessToken;
this.refreshToken = response.refreshToken;
this.expiresInSeconds = response.expiresInSeconds;
if (idpInfo) {
this.idpInfo = idpInfo;
}
}
removeAccessToken() {
this.accessToken = undefined;
}
removeRefreshToken() {
this.refreshToken = undefined;
}
}
exports.TokenCache = TokenCache;
//# sourceMappingURL=token_cache.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"token_cache.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/token_cache.ts"],"names":[],"mappings":";;;AAAA,0CAAkD;AAGlD,MAAM,cAAe,SAAQ,wBAAgB;CAAG;AAEhD,gBAAgB;AAChB,MAAa,UAAU;IAMrB,IAAI,cAAc;QAChB,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;IAC7B,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,cAAc,CAAC,oDAAoD,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,eAAe;QACb,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,MAAM,IAAI,cAAc,CAAC,oDAAoD,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,cAAc,CAAC,oDAAoD,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,GAAG,CAAC,QAAsB,EAAE,OAAiB;QAC3C,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;QACxC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC;QAC1C,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAC;QAClD,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACzB,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;IAChC,CAAC;CACF;AAvDD,gCAuDC"}

View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tokenMachineCallback = void 0;
const fs = require("fs");
const process = require("process");
const error_1 = require("../../../error");
/** Error for when the token is missing in the environment. */
const TOKEN_MISSING_ERROR = 'OIDC_TOKEN_FILE must be set in the environment.';
/**
* The callback function to be used in the automated callback workflow.
* @param params - The OIDC callback parameters.
* @returns The OIDC response.
*/
const tokenMachineCallback = async () => {
const tokenFile = process.env.OIDC_TOKEN_FILE;
if (!tokenFile) {
throw new error_1.MongoAWSError(TOKEN_MISSING_ERROR);
}
const token = await fs.promises.readFile(tokenFile, 'utf8');
return { accessToken: token };
};
exports.tokenMachineCallback = tokenMachineCallback;
//# sourceMappingURL=token_machine_workflow.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"token_machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/token_machine_workflow.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AACzB,mCAAmC;AAEnC,0CAA+C;AAG/C,8DAA8D;AAC9D,MAAM,mBAAmB,GAAG,iDAAiD,CAAC;AAE9E;;;;GAIG;AACI,MAAM,oBAAoB,GAAyB,KAAK,IAA2B,EAAE;IAC1F,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,oBAAoB,wBAO/B"}

26
backend/node_modules/mongodb/lib/cmap/auth/plain.js generated vendored Normal file
View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Plain = void 0;
const bson_1 = require("../../bson");
const error_1 = require("../../error");
const utils_1 = require("../../utils");
const auth_provider_1 = require("./auth_provider");
class Plain extends auth_provider_1.AuthProvider {
async auth(authContext) {
const { connection, credentials } = authContext;
if (!credentials) {
throw new error_1.MongoMissingCredentialsError('AuthContext must provide credentials.');
}
const { username, password } = credentials;
const payload = new bson_1.Binary(bson_1.ByteUtils.fromUTF8(`\x00${username}\x00${password}`));
const command = {
saslStart: 1,
mechanism: 'PLAIN',
payload: payload,
autoAuthorize: 1
};
await connection.command((0, utils_1.ns)('$external.$cmd'), command, undefined);
}
}
exports.Plain = Plain;
//# sourceMappingURL=plain.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"plain.js","sourceRoot":"","sources":["../../../src/cmap/auth/plain.ts"],"names":[],"mappings":";;;AAAA,qCAA+C;AAC/C,uCAA2D;AAC3D,uCAAiC;AACjC,mDAAiE;AAEjE,MAAa,KAAM,SAAQ,4BAAY;IAC5B,KAAK,CAAC,IAAI,CAAC,WAAwB;QAC1C,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC;QAChD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,oCAA4B,CAAC,uCAAuC,CAAC,CAAC;QAClF,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC;QAE3C,MAAM,OAAO,GAAG,IAAI,aAAM,CAAC,gBAAS,CAAC,QAAQ,CAAC,OAAO,QAAQ,OAAO,QAAQ,EAAE,CAAC,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,OAAO;YAClB,OAAO,EAAE,OAAO;YAChB,aAAa,EAAE,CAAC;SACjB,CAAC;QAEF,MAAM,UAAU,CAAC,OAAO,CAAC,IAAA,UAAE,EAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACrE,CAAC;CACF;AAnBD,sBAmBC"}

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AUTH_MECHS_AUTH_SRC_EXTERNAL = exports.AuthMechanism = void 0;
/** @public */
exports.AuthMechanism = Object.freeze({
MONGODB_AWS: 'MONGODB-AWS',
MONGODB_DEFAULT: 'DEFAULT',
MONGODB_GSSAPI: 'GSSAPI',
MONGODB_PLAIN: 'PLAIN',
MONGODB_SCRAM_SHA1: 'SCRAM-SHA-1',
MONGODB_SCRAM_SHA256: 'SCRAM-SHA-256',
MONGODB_X509: 'MONGODB-X509',
MONGODB_OIDC: 'MONGODB-OIDC'
});
/** @internal */
exports.AUTH_MECHS_AUTH_SRC_EXTERNAL = new Set([
exports.AuthMechanism.MONGODB_GSSAPI,
exports.AuthMechanism.MONGODB_AWS,
exports.AuthMechanism.MONGODB_OIDC,
exports.AuthMechanism.MONGODB_X509
]);
//# sourceMappingURL=providers.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../../src/cmap/auth/providers.ts"],"names":[],"mappings":";;;AAAA,cAAc;AACD,QAAA,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,WAAW,EAAE,aAAa;IAC1B,eAAe,EAAE,SAAS;IAC1B,cAAc,EAAE,QAAQ;IACxB,aAAa,EAAE,OAAO;IACtB,kBAAkB,EAAE,aAAa;IACjC,oBAAoB,EAAE,eAAe;IACrC,YAAY,EAAE,cAAc;IAC5B,YAAY,EAAE,cAAc;CACpB,CAAC,CAAC;AAKZ,gBAAgB;AACH,QAAA,4BAA4B,GAAG,IAAI,GAAG,CAAgB;IACjE,qBAAa,CAAC,cAAc;IAC5B,qBAAa,CAAC,WAAW;IACzB,qBAAa,CAAC,YAAY;IAC1B,qBAAa,CAAC,YAAY;CAC3B,CAAC,CAAC"}

267
backend/node_modules/mongodb/lib/cmap/auth/scram.js generated vendored Normal file
View File

@@ -0,0 +1,267 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScramSHA256 = exports.ScramSHA1 = void 0;
const saslprep_1 = require("@mongodb-js/saslprep");
const bson_1 = require("../../bson");
const error_1 = require("../../error");
const utils_1 = require("../../utils");
const auth_provider_1 = require("./auth_provider");
const providers_1 = require("./providers");
class ScramSHA extends auth_provider_1.AuthProvider {
constructor(cryptoMethod) {
super();
this.cryptoMethod = cryptoMethod || 'sha1';
}
async prepare(handshakeDoc, authContext) {
const cryptoMethod = this.cryptoMethod;
const credentials = authContext.credentials;
if (!credentials) {
throw new error_1.MongoMissingCredentialsError('AuthContext must provide credentials.');
}
const nonce = await (0, utils_1.randomBytes)(24);
// store the nonce for later use
authContext.nonce = nonce;
const request = {
...handshakeDoc,
speculativeAuthenticate: {
...makeFirstMessage(cryptoMethod, credentials, nonce),
db: credentials.source
}
};
return request;
}
async auth(authContext) {
const { reauthenticating, response } = authContext;
if (response?.speculativeAuthenticate && !reauthenticating) {
return await continueScramConversation(this.cryptoMethod, response.speculativeAuthenticate, authContext);
}
return await executeScram(this.cryptoMethod, authContext);
}
}
function cleanUsername(username) {
return username.replace('=', '=3D').replace(',', '=2C');
}
function clientFirstMessageBare(username, nonce) {
// NOTE: This is done b/c Javascript uses UTF-16, but the server is hashing in UTF-8.
// Since the username is not sasl-prep-d, we need to do this here.
return bson_1.ByteUtils.concat([
bson_1.ByteUtils.fromUTF8('n='),
bson_1.ByteUtils.fromUTF8(username),
bson_1.ByteUtils.fromUTF8(',r='),
bson_1.ByteUtils.fromUTF8(bson_1.ByteUtils.toBase64(nonce))
]);
}
function makeFirstMessage(cryptoMethod, credentials, nonce) {
const username = cleanUsername(credentials.username);
const mechanism = cryptoMethod === 'sha1' ? providers_1.AuthMechanism.MONGODB_SCRAM_SHA1 : providers_1.AuthMechanism.MONGODB_SCRAM_SHA256;
// NOTE: This is done b/c Javascript uses UTF-16, but the server is hashing in UTF-8.
// Since the username is not sasl-prep-d, we need to do this here.
return {
saslStart: 1,
mechanism,
payload: new bson_1.Binary(bson_1.ByteUtils.concat([bson_1.ByteUtils.fromUTF8('n,,'), clientFirstMessageBare(username, nonce)])),
autoAuthorize: 1,
options: { skipEmptyExchange: true }
};
}
async function executeScram(cryptoMethod, authContext) {
const { connection, credentials } = authContext;
if (!credentials) {
throw new error_1.MongoMissingCredentialsError('AuthContext must provide credentials.');
}
if (!authContext.nonce) {
throw new error_1.MongoInvalidArgumentError('AuthContext must contain a valid nonce property');
}
const nonce = authContext.nonce;
const db = credentials.source;
const saslStartCmd = makeFirstMessage(cryptoMethod, credentials, nonce);
const response = await connection.command((0, utils_1.ns)(`${db}.$cmd`), saslStartCmd, undefined);
await continueScramConversation(cryptoMethod, response, authContext);
}
async function continueScramConversation(cryptoMethod, response, authContext) {
const connection = authContext.connection;
const credentials = authContext.credentials;
if (!credentials) {
throw new error_1.MongoMissingCredentialsError('AuthContext must provide credentials.');
}
if (!authContext.nonce) {
throw new error_1.MongoInvalidArgumentError('Unable to continue SCRAM without valid nonce');
}
const nonce = authContext.nonce;
const db = credentials.source;
const username = cleanUsername(credentials.username);
const password = credentials.password;
const processedPassword = cryptoMethod === 'sha256' ? (0, saslprep_1.saslprep)(password) : passwordDigest(username, password);
const payload = bson_1.ByteUtils.isUint8Array(response.payload)
? new bson_1.Binary(response.payload)
: response.payload;
const dict = parsePayload(payload);
const iterations = parseInt(dict.i, 10);
if (iterations && iterations < 4096) {
// TODO(NODE-3483)
throw new error_1.MongoRuntimeError(`Server returned an invalid iteration count ${iterations}`);
}
const salt = dict.s;
const rnonce = dict.r;
if (rnonce.startsWith('nonce')) {
// TODO(NODE-3483)
throw new error_1.MongoRuntimeError(`Server returned an invalid nonce: ${rnonce}`);
}
// Set up start of proof
const withoutProof = `c=biws,r=${rnonce}`;
const saltedPassword = await HI(processedPassword, bson_1.ByteUtils.fromBase64(salt), iterations, cryptoMethod);
const clientKey = await HMAC(cryptoMethod, saltedPassword, 'Client Key');
const serverKey = await HMAC(cryptoMethod, saltedPassword, 'Server Key');
const storedKey = await H(cryptoMethod, clientKey);
const authMessage = [
clientFirstMessageBare(username, nonce),
payload.toString('utf8'),
withoutProof
].join(',');
const clientSignature = await HMAC(cryptoMethod, storedKey, authMessage);
const clientProof = `p=${xor(clientKey, clientSignature)}`;
const clientFinal = [withoutProof, clientProof].join(',');
const serverSignature = await HMAC(cryptoMethod, serverKey, authMessage);
const saslContinueCmd = {
saslContinue: 1,
conversationId: response.conversationId,
payload: new bson_1.Binary(bson_1.ByteUtils.fromUTF8(clientFinal))
};
const r = await connection.command((0, utils_1.ns)(`${db}.$cmd`), saslContinueCmd, undefined);
const parsedResponse = parsePayload(r.payload);
if (!compareDigest(bson_1.ByteUtils.fromBase64(parsedResponse.v), serverSignature)) {
throw new error_1.MongoRuntimeError('Server returned an invalid signature');
}
if (r.done !== false) {
// If the server sends r.done === true we can save one RTT
return;
}
const retrySaslContinueCmd = {
saslContinue: 1,
conversationId: r.conversationId,
payload: bson_1.ByteUtils.allocate(0)
};
await connection.command((0, utils_1.ns)(`${db}.$cmd`), retrySaslContinueCmd, undefined);
}
function parsePayload(payload) {
const payloadStr = payload.toString('utf8');
const dict = {};
const parts = payloadStr.split(',');
for (let i = 0; i < parts.length; i++) {
const valueParts = (parts[i].match(/^([^=]*)=(.*)$/) ?? []).slice(1);
dict[valueParts[0]] = valueParts[1];
}
return dict;
}
function passwordDigest(username, password) {
if (typeof username !== 'string') {
throw new error_1.MongoInvalidArgumentError('Username must be a string');
}
if (typeof password !== 'string') {
throw new error_1.MongoInvalidArgumentError('Password must be a string');
}
if (password.length === 0) {
throw new error_1.MongoInvalidArgumentError('Password cannot be empty');
}
let nodeCrypto;
try {
// TODO: NODE-7424 - remove dependency on 'crypto' for SCRAM-SHA-1 authentication
// eslint-disable-next-line @typescript-eslint/no-require-imports
nodeCrypto = require('crypto');
}
catch (e) {
throw new error_1.MongoRuntimeError('Node.js crypto module is required for SCRAM-SHA-1 authentication', {
cause: e
});
}
try {
const md5 = nodeCrypto.createHash('md5');
md5.update(`${username}:mongo:${password}`, 'utf8');
return md5.digest('hex');
}
catch (err) {
if (nodeCrypto.getFips()) {
// This error is (slightly) more helpful than what comes from OpenSSL directly, e.g.
// 'Error: error:060800C8:digital envelope routines:EVP_DigestInit_ex:disabled for FIPS'
throw new Error('Auth mechanism SCRAM-SHA-1 is not supported in FIPS mode');
}
throw err;
}
}
// XOR two buffers
function xor(a, b) {
const length = Math.max(a.length, b.length);
const res = [];
for (let i = 0; i < length; i += 1) {
res.push(a[i] ^ b[i]);
}
return bson_1.ByteUtils.toBase64(bson_1.ByteUtils.fromNumberArray(res));
}
async function H(method, text) {
const buffer = await crypto.subtle.digest(method === 'sha256' ? 'SHA-256' : 'SHA-1', text);
return new Uint8Array(buffer);
}
async function HMAC(method, key, text) {
const keyBuffer = bson_1.ByteUtils.toLocalBufferType(key);
const cryptoKey = await crypto.subtle.importKey('raw', keyBuffer, { name: 'HMAC', hash: { name: method === 'sha256' ? 'SHA-256' : 'SHA-1' } }, false, ['sign', 'verify']);
const textData = typeof text === 'string' ? new TextEncoder().encode(text) : text;
const textBuffer = bson_1.ByteUtils.toLocalBufferType(textData);
const signature = await crypto.subtle.sign('HMAC', cryptoKey, textBuffer);
return new Uint8Array(signature);
}
let _hiCache = {};
let _hiCacheCount = 0;
function _hiCachePurge() {
_hiCache = {};
_hiCacheCount = 0;
}
const hiLengthMap = {
sha256: 32,
sha1: 20
};
async function HI(data, salt, iterations, cryptoMethod) {
// omit the work if already generated
const key = [data, bson_1.ByteUtils.toBase64(salt), iterations].join('_');
if (_hiCache[key] != null) {
return _hiCache[key];
}
const keyMaterial = await crypto.subtle.importKey('raw', new TextEncoder().encode(data), { name: 'PBKDF2' }, false, ['deriveBits']);
const params = {
name: 'PBKDF2',
salt: salt,
iterations: iterations,
hash: { name: cryptoMethod === 'sha256' ? 'SHA-256' : 'SHA-1' }
};
const derivedBits = await crypto.subtle.deriveBits(params, keyMaterial, hiLengthMap[cryptoMethod] * 8);
const saltedData = new Uint8Array(derivedBits);
// cache a copy to speed up the next lookup, but prevent unbounded cache growth
if (_hiCacheCount >= 200) {
_hiCachePurge();
}
_hiCache[key] = saltedData;
_hiCacheCount += 1;
return saltedData;
}
function compareDigest(lhs, rhs) {
if (lhs.length !== rhs.length) {
return false;
}
let result = 0;
for (let i = 0; i < lhs.length; i++) {
result |= lhs[i] ^ rhs[i];
}
return result === 0;
}
class ScramSHA1 extends ScramSHA {
constructor() {
super('sha1');
}
}
exports.ScramSHA1 = ScramSHA1;
class ScramSHA256 extends ScramSHA {
constructor() {
super('sha256');
}
}
exports.ScramSHA256 = ScramSHA256;
//# sourceMappingURL=scram.js.map

File diff suppressed because one or more lines are too long

36
backend/node_modules/mongodb/lib/cmap/auth/x509.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.X509 = void 0;
const error_1 = require("../../error");
const utils_1 = require("../../utils");
const auth_provider_1 = require("./auth_provider");
class X509 extends auth_provider_1.AuthProvider {
async prepare(handshakeDoc, authContext) {
const { credentials } = authContext;
if (!credentials) {
throw new error_1.MongoMissingCredentialsError('AuthContext must provide credentials.');
}
return { ...handshakeDoc, speculativeAuthenticate: x509AuthenticateCommand(credentials) };
}
async auth(authContext) {
const connection = authContext.connection;
const credentials = authContext.credentials;
if (!credentials) {
throw new error_1.MongoMissingCredentialsError('AuthContext must provide credentials.');
}
const response = authContext.response;
if (response?.speculativeAuthenticate) {
return;
}
await connection.command((0, utils_1.ns)('$external.$cmd'), x509AuthenticateCommand(credentials), undefined);
}
}
exports.X509 = X509;
function x509AuthenticateCommand(credentials) {
const command = { authenticate: 1, mechanism: 'MONGODB-X509' };
if (credentials.username) {
command.user = credentials.username;
}
return command;
}
//# sourceMappingURL=x509.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"x509.js","sourceRoot":"","sources":["../../../src/cmap/auth/x509.ts"],"names":[],"mappings":";;;AACA,uCAA2D;AAC3D,uCAAiC;AAEjC,mDAAiE;AAGjE,MAAa,IAAK,SAAQ,4BAAY;IAC3B,KAAK,CAAC,OAAO,CACpB,YAA+B,EAC/B,WAAwB;QAExB,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC;QACpC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,oCAA4B,CAAC,uCAAuC,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,EAAE,GAAG,YAAY,EAAE,uBAAuB,EAAE,uBAAuB,CAAC,WAAW,CAAC,EAAE,CAAC;IAC5F,CAAC;IAEQ,KAAK,CAAC,IAAI,CAAC,WAAwB;QAC1C,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC;QAC1C,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC;QAC5C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,oCAA4B,CAAC,uCAAuC,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;QAEtC,IAAI,QAAQ,EAAE,uBAAuB,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QAED,MAAM,UAAU,CAAC,OAAO,CAAC,IAAA,UAAE,EAAC,gBAAgB,CAAC,EAAE,uBAAuB,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,CAAC;IAClG,CAAC;CACF;AA1BD,oBA0BC;AAED,SAAS,uBAAuB,CAAC,WAA6B;IAC5D,MAAM,OAAO,GAAa,EAAE,YAAY,EAAE,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;IACzE,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}