All files / src mongo_client_auth_providers.ts

90% Statements 36/40
70% Branches 7/10
90.9% Functions 10/11
90% Lines 36/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96  396x   396x 396x 396x 396x 396x 396x 396x 396x 396x 396x     396x           87x                   95x 10x 13x 1218x 1582910x 15x               396x 2000442x                             3605373x 3605373x 2021021x     1584352x 1584352x 4x     1584348x 1584348x 1584348x               10x   10x     10x 10x 10x         10x      
import { type AuthProvider } from './cmap/auth/auth_provider';
import { GSSAPI } from './cmap/auth/gssapi';
import { type AuthMechanismProperties } from './cmap/auth/mongo_credentials';
import { MongoDBAWS } from './cmap/auth/mongodb_aws';
import { MongoDBOIDC, OIDC_WORKFLOWS, type Workflow } from './cmap/auth/mongodb_oidc';
import { AutomatedCallbackWorkflow } from './cmap/auth/mongodb_oidc/automated_callback_workflow';
import { HumanCallbackWorkflow } from './cmap/auth/mongodb_oidc/human_callback_workflow';
import { TokenCache } from './cmap/auth/mongodb_oidc/token_cache';
import { Plain } from './cmap/auth/plain';
import { AuthMechanism } from './cmap/auth/providers';
import { ScramSHA1, ScramSHA256 } from './cmap/auth/scram';
import { X509 } from './cmap/auth/x509';
import { MongoInvalidArgumentError } from './error';
 
/** @internal */
const AUTH_PROVIDERS = new Map<
  AuthMechanism | string,
  (authMechanismProperties: AuthMechanismProperties) => AuthProvider
>([
  [
    AuthMechanism.MONGODB_AWS,
    ({ AWS_CREDENTIAL_PROVIDER }) => new MongoDBAWS(AWS_CREDENTIAL_PROVIDER)
  ],
  [
    AuthMechanism.MONGODB_CR,
    () => {
      throw new MongoInvalidArgumentError(
        'MONGODB-CR is no longer a supported auth mechanism in MongoDB 4.0+'
      );
    }
  ],
  [AuthMechanism.MONGODB_GSSAPI, () => new GSSAPI()],
  [AuthMechanism.MONGODB_OIDC, properties => new MongoDBOIDC(getWorkflow(properties))],
  [AuthMechanism.MONGODB_PLAIN, () => new Plain()],
  [AuthMechanism.MONGODB_SCRAM_SHA1, () => new ScramSHA1()],
  [AuthMechanism.MONGODB_SCRAM_SHA256, () => new ScramSHA256()],
  [AuthMechanism.MONGODB_X509, () => new X509()]
]);
 
/**
 * Create a set of providers per client
 * to avoid sharing the provider's cache between different clients.
 * @internal
 */
export class MongoClientAuthProviders {
  private existingProviders: Map<AuthMechanism | string, AuthProvider> = new Map();
 
  /**
   * Get or create an authentication provider based on the provided mechanism.
   * We don't want to create all providers at once, as some providers may not be used.
   * @param name - The name of the provider to get or create.
   * @param credentials - The credentials.
   * @returns The provider.
   * @throws MongoInvalidArgumentError if the mechanism is not supported.
   * @internal
   */
  getOrCreateProvider(
    name: AuthMechanism | string,
    authMechanismProperties: AuthMechanismProperties
  ): AuthProvider {
    const authProvider = this.existingProviders.get(name);
    if (authProvider) {
      return authProvider;
    }
 
    const providerFunction = AUTH_PROVIDERS.get(name);
    if (!providerFunction) {
      throw new MongoInvalidArgumentError(`authMechanism ${name} not supported`);
    }
 
    const provider = providerFunction(authMechanismProperties);
    this.existingProviders.set(name, provider);
    return provider;
  }
}
 
/**
 * Gets either a device workflow or callback workflow.
 */
function getWorkflow(authMechanismProperties: AuthMechanismProperties): Workflow {
  Iif (authMechanismProperties.OIDC_HUMAN_CALLBACK) {
    return new HumanCallbackWorkflow(new TokenCache(), authMechanismProperties.OIDC_HUMAN_CALLBACK);
  } else Iif (authMechanismProperties.OIDC_CALLBACK) {
    return new AutomatedCallbackWorkflow(new TokenCache(), authMechanismProperties.OIDC_CALLBACK);
  } else {
    const environment = authMechanismProperties.ENVIRONMENT;
    const workflow = OIDC_WORKFLOWS.get(environment)?.();
    Iif (!workflow) {
      throw new MongoInvalidArgumentError(
        `Could not load workflow for environment ${authMechanismProperties.ENVIRONMENT}`
      );
    }
    return workflow;
  }
}