UNPKG

botbuilder-core

Version:

Core components for Microsoft Bot Builder. Components in this library can run either in a browser or on the server.

287 lines (253 loc) 12.7 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import * as z from 'zod'; import { Activity } from 'botframework-schema'; import { Configuration } from 'botbuilder-dialogs-adaptive-runtime-core'; import { AuthenticateRequestResult, AuthenticationConfiguration, AuthenticationConstants, BotFrameworkAuthentication, BotFrameworkAuthenticationFactory, BotFrameworkClient, ClaimsIdentity, ConnectorClientOptions, ConnectorFactory, ServiceClientCredentialsFactory, UserTokenClient, AseChannelValidation, } from 'botframework-connector'; import { ConfigurationServiceClientCredentialFactory, ConfigurationServiceClientCredentialFactoryOptions, } from './configurationServiceClientCredentialFactory'; const TypedOptions = z .object({ /** * The ID assigned to your bot in the [Bot Framework Portal](https://dev.botframework.com/). */ MicrosoftAppId: z.string(), /** * The tenant id assigned to your bot in the [Bot Framework Portal](https://dev.botframework.com/). */ MicrosoftAppTenantId: z.string(), /** * (Optional) The OAuth URL used to get a token from OAuthApiClient. The "OAuthUrl" member takes precedence over this value. */ [AuthenticationConstants.OAuthUrlKey]: z.string(), /** * (Optional) The OpenID metadata document used for authenticating tokens coming from the channel. The "ToBotFromChannelOpenIdMetadataUrl" member takes precedence over this value. */ [AuthenticationConstants.BotOpenIdMetadataKey]: z.string().nullable(), /** * A string used to indicate if which cloud the bot is operating in (e.g. Public Azure or US Government). * * @remarks * A `null` or `''` value indicates Public Azure, whereas [GovernmentConstants.ChannelService](xref:botframework-connector.GovernmentConstants.ChannelService) indicates the bot is operating in the US Government cloud. * * Other values result in a custom authentication configuration derived from the values passed in on the [ConfigurationBotFrameworkAuthenticationOptions](xef:botbuilder-core.ConfigurationBotFrameworkAuthenticationOptions) instance. */ [AuthenticationConstants.ChannelService]: z.string(), /** * Flag indicating whether or not to validate the address. */ ValidateAuthority: z.union([z.string(), z.boolean()]), /** * The Login URL used to specify the tenant from which the bot should obtain access tokens from. */ ToChannelFromBotLoginUrl: z.string(), /** * The Oauth scope to request. * * @remarks * This value is used when fetching a token to indicate the ultimate recipient or `audience` of an activity sent using these credentials. */ ToChannelFromBotOAuthScope: z.string(), /** * The Token issuer for signed requests to the channel. */ ToBotFromChannelTokenIssuer: z.string(), /** * The OAuth URL used to get a token from OAuthApiClient. */ OAuthUrl: z.string(), /** * The OpenID metadata document used for authenticating tokens coming from the channel. */ ToBotFromChannelOpenIdMetadataUrl: z.string(), /** * The The OpenID metadata document used for authenticating tokens coming from the Emulator. */ ToBotFromEmulatorOpenIdMetadataUrl: z.string(), /** * A value for the CallerId. */ CallerId: z.string(), /** * Certificate thumbprint to authenticate the appId against AAD. */ [AuthenticationConstants.CertificateThumbprint]: z.string(), /** * Certificate key to authenticate the appId against AAD. */ [AuthenticationConstants.CertificatePrivateKey]: z.string(), }) .partial(); /** * Contains settings used to configure a [ConfigurationBotFrameworkAuthentication](xref:botbuilder-core.ConfigurationBotFrameworkAuthentication) instance. */ export type ConfigurationBotFrameworkAuthenticationOptions = z.infer<typeof TypedOptions>; /** * Creates a [BotFrameworkAuthentication](xref:botframework-connector.BotFrameworkAuthentication) instance from an object with the authentication values or a [Configuration](xref:botbuilder-dialogs-adaptive-runtime-core.Configuration) instance. */ export class ConfigurationBotFrameworkAuthentication extends BotFrameworkAuthentication { private readonly inner: BotFrameworkAuthentication; /** * Initializes a new instance of the [ConfigurationBotFrameworkAuthentication](xref:botbuilder-core.ConfigurationBotFrameworkAuthentication) class. * * @param botFrameworkAuthConfig A [ConfigurationBotFrameworkAuthenticationOptions](xref:botbuilder-core.ConfigurationBotFrameworkAuthenticationOptions) object. * @param credentialsFactory A [ServiceClientCredentialsFactory](xref:botframework-connector.ServiceClientCredentialsFactory) instance. * @param authConfiguration A [Configuration](xref:botframework-connector.AuthenticationConfiguration) object. * @param botFrameworkClientFetch A custom Fetch implementation to be used in the [BotFrameworkClient](xref:botframework-connector.BotFrameworkClient). * @param connectorClientOptions A [ConnectorClientOptions](xref:botframework-connector.ConnectorClientOptions) object. */ constructor( botFrameworkAuthConfig: ConfigurationBotFrameworkAuthenticationOptions = {}, credentialsFactory?: ServiceClientCredentialsFactory, authConfiguration?: AuthenticationConfiguration, botFrameworkClientFetch?: (input: RequestInfo, init?: RequestInit) => Promise<Response>, connectorClientOptions: ConnectorClientOptions = {}, ) { super(); try { AseChannelValidation.init(botFrameworkAuthConfig); const typedBotFrameworkAuthConfig = TypedOptions.nonstrict().parse(botFrameworkAuthConfig); const { CallerId, ChannelService, OAuthUrl = typedBotFrameworkAuthConfig[AuthenticationConstants.OAuthUrlKey], ToBotFromChannelOpenIdMetadataUrl = typedBotFrameworkAuthConfig[ AuthenticationConstants.BotOpenIdMetadataKey ], ToBotFromChannelTokenIssuer, ToBotFromEmulatorOpenIdMetadataUrl, ToChannelFromBotLoginUrl, ToChannelFromBotOAuthScope, } = typedBotFrameworkAuthConfig; let ValidateAuthority = true; try { ValidateAuthority = Boolean(JSON.parse(`${typedBotFrameworkAuthConfig.ValidateAuthority ?? true}`)); } catch (_err) { // no-op } this.inner = BotFrameworkAuthenticationFactory.create( ChannelService, ValidateAuthority, ToChannelFromBotLoginUrl, ToChannelFromBotOAuthScope, ToBotFromChannelTokenIssuer, OAuthUrl, ToBotFromChannelOpenIdMetadataUrl, ToBotFromEmulatorOpenIdMetadataUrl, CallerId, credentialsFactory ?? new ConfigurationServiceClientCredentialFactory( typedBotFrameworkAuthConfig as ConfigurationServiceClientCredentialFactoryOptions, ), authConfiguration ?? { requiredEndorsements: [] }, botFrameworkClientFetch, connectorClientOptions, ); } catch (err) { // Throw a new error with the validation details prominently featured. if (z.instanceof(z.ZodError).safeParse(err).success) { throw new Error(JSON.stringify(err.errors, null, 2)); } throw err; } } /** * Authenticate Bot Framework Protocol requests to Skills. * * @param authHeader The http auth header received in the skill request. * @returns {Promise<ClaimsIdentity>} A [ClaimsIdentity](xref:botframework-connector.ClaimsIdentity). */ authenticateChannelRequest(authHeader: string): Promise<ClaimsIdentity> { return this.inner.authenticateChannelRequest(authHeader); } /** * Validate Bot Framework Protocol requests. * * @param activity The inbound Activity. * @param authHeader The HTTP auth header. * @returns {Promise<AuthenticateRequestResult>} An [AuthenticateRequestResult](xref:botframework-connector.AuthenticateRequestResult). */ authenticateRequest(activity: Activity, authHeader: string): Promise<AuthenticateRequestResult> { return this.inner.authenticateRequest(activity, authHeader); } /** * Validate Bot Framework Protocol requests. * * @param authHeader The HTTP auth header. * @param channelIdHeader The channel ID HTTP header. * @returns {Promise<AuthenticateRequestResult>} An [AuthenticateRequestResult](xref:botframework-connector.AuthenticateRequestResult). */ authenticateStreamingRequest(authHeader: string, channelIdHeader: string): Promise<AuthenticateRequestResult> { return this.inner.authenticateStreamingRequest(authHeader, channelIdHeader); } /** * Creates a BotFrameworkClient for calling Skills. * * @returns A [BotFrameworkClient](xref:botframework-connector.BotFrameworkClient). */ createBotFrameworkClient(): BotFrameworkClient { return this.inner.createBotFrameworkClient(); } /** * Creates a ConnectorFactory that can be used to create ConnectorClients that can use credentials from this particular Cloud Environment. * * @param claimsIdentity The inbound Activity's ClaimsIdentity. * @returns A [ConnectorFactory](xref:botframework-connector.ConnectorFactory). */ createConnectorFactory(claimsIdentity: ClaimsIdentity): ConnectorFactory { return this.inner.createConnectorFactory(claimsIdentity); } /** * Creates the appropriate UserTokenClient instance. * * @param claimsIdentity The inbound Activity's ClaimsIdentity. * @returns {Promise<UserTokenClient>} An [UserTokenClient](xref:botframework-connector.UserTokenClient). */ createUserTokenClient(claimsIdentity: ClaimsIdentity): Promise<UserTokenClient> { return this.inner.createUserTokenClient(claimsIdentity); } } /** * Creates a new instance of the [ConfigurationBotFrameworkAuthentication](xref:botbuilder-core.ConfigurationBotFrameworkAuthentication) class. * * @remarks * The [Configuration](xref:botbuilder-dialogs-adaptive-runtime-core.Configuration) instance provided to the constructor should * have the desired authentication values available at the root, using the properties of [ConfigurationBotFrameworkAuthenticationOptions](xref:botbuilder-core.ConfigurationBotFrameworkAuthenticationOptions) as its keys. * @param configuration A [Configuration](xref:botbuilder-dialogs-adaptive-runtime-core.Configuration) instance. * @param credentialsFactory A [ServiceClientCredentialsFactory](xref:botframework-connector.ServiceClientCredentialsFactory) instance. * @param authConfiguration A [Configuration](xref:botframework-connector.AuthenticationConfiguration) object. * @param botFrameworkClientFetch A custom Fetch implementation to be used in the [BotFrameworkClient](xref:botframework-connector.BotFrameworkClient). * @param connectorClientOptions A [ConnectorClientOptions](xref:botframework-connector.ConnectorClientOptions) object. * @returns A [ConfigurationBotFrameworkAuthentication](xref:botbuilder-core.ConfigurationBotFrameworkAuthentication) instance. */ export function createBotFrameworkAuthenticationFromConfiguration( configuration: Configuration, credentialsFactory?: ServiceClientCredentialsFactory, authConfiguration?: AuthenticationConfiguration, botFrameworkClientFetch?: (input: RequestInfo, init?: RequestInit) => Promise<Response>, connectorClientOptions: ConnectorClientOptions = {}, ): BotFrameworkAuthentication { const botFrameworkAuthConfig = configuration?.get<ConfigurationBotFrameworkAuthenticationOptions>(); return new ConfigurationBotFrameworkAuthentication( botFrameworkAuthConfig, credentialsFactory, authConfiguration, botFrameworkClientFetch, connectorClientOptions, ); }