124 lines
No EOL
7.9 KiB
JavaScript
124 lines
No EOL
7.9 KiB
JavaScript
"use strict";
|
|
/**
|
|
* @module botframework-connector
|
|
*/
|
|
/**
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License.
|
|
*/
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.EnterpriseChannelValidation = void 0;
|
|
const authenticationConfiguration_1 = require("./authenticationConfiguration");
|
|
const authenticationConstants_1 = require("./authenticationConstants");
|
|
const channelValidation_1 = require("./channelValidation");
|
|
const jwtTokenExtractor_1 = require("./jwtTokenExtractor");
|
|
const authenticationError_1 = require("./authenticationError");
|
|
const botframework_schema_1 = require("botframework-schema");
|
|
/**
|
|
* @deprecated Use `ConfigurationBotFrameworkAuthentication` instead to perform enterprise channel validation.
|
|
*/
|
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
var EnterpriseChannelValidation;
|
|
(function (EnterpriseChannelValidation) {
|
|
/**
|
|
* TO BOT FROM CHANNEL: Token validation parameters when connecting to a bot
|
|
*/
|
|
EnterpriseChannelValidation.ToBotFromEnterpriseChannelTokenValidationParameters = {
|
|
issuer: [authenticationConstants_1.AuthenticationConstants.ToBotFromChannelTokenIssuer],
|
|
audience: undefined,
|
|
clockTolerance: 5 * 60,
|
|
ignoreExpiration: false,
|
|
};
|
|
/**
|
|
* Validate the incoming Auth Header as a token sent from the Bot Framework Service.
|
|
* A token issued by the Bot Framework emulator will FAIL this check.
|
|
*
|
|
* @param {string} authHeader The raw HTTP header in the format: "Bearer [longString]"
|
|
* @param {ICredentialProvider} credentials The user defined set of valid credentials, such as the AppId.
|
|
* @param {string} serviceUrl The ServiceUrl Claim value that must match in the identity.
|
|
* @param channelId The ID of the channel to validate.
|
|
* @param channelService The channelService value that distinguishes public Azure from US Government Azure.
|
|
* @returns {Promise<ClaimsIdentity>} A valid ClaimsIdentity.
|
|
*/
|
|
function authenticateChannelTokenWithServiceUrl(authHeader, credentials, serviceUrl, channelId, channelService) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const identity = yield authenticateChannelToken(authHeader, credentials, channelId, channelService);
|
|
const serviceUrlClaim = identity.getClaimValue(authenticationConstants_1.AuthenticationConstants.ServiceUrlClaim);
|
|
if (serviceUrlClaim !== serviceUrl) {
|
|
// Claim must match. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized. ServiceUrl claim do not match.', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
return identity;
|
|
});
|
|
}
|
|
EnterpriseChannelValidation.authenticateChannelTokenWithServiceUrl = authenticateChannelTokenWithServiceUrl;
|
|
/**
|
|
* Validate the incoming Auth Header as a token sent from the Bot Framework Service.
|
|
* A token issued by the Bot Framework emulator will FAIL this check.
|
|
*
|
|
* @param {string} authHeader The raw HTTP header in the format: "Bearer [longString]"
|
|
* @param {ICredentialProvider} credentials The user defined set of valid credentials, such as the AppId.
|
|
* @param channelId The ID of the channel to validate.
|
|
* @param channelService The channelService value that distinguishes public Azure from US Government Azure.
|
|
* @param authConfig The authentication configuration.
|
|
* @returns {Promise<ClaimsIdentity>} A valid ClaimsIdentity.
|
|
*/
|
|
function authenticateChannelToken(authHeader, credentials, channelId, channelService, authConfig = new authenticationConfiguration_1.AuthenticationConfiguration()) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const tokenExtractor = new jwtTokenExtractor_1.JwtTokenExtractor(EnterpriseChannelValidation.ToBotFromEnterpriseChannelTokenValidationParameters, channelValidation_1.ChannelValidation.OpenIdMetadataEndpoint
|
|
? channelValidation_1.ChannelValidation.OpenIdMetadataEndpoint
|
|
: authenticationConstants_1.AuthenticationConstants.ToBotFromEnterpriseChannelOpenIdMetadataUrlFormat.replace('{channelService}', channelService), authenticationConstants_1.AuthenticationConstants.AllowedSigningAlgorithms);
|
|
const identity = yield tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId, authConfig.requiredEndorsements);
|
|
return yield validateIdentity(identity, credentials);
|
|
});
|
|
}
|
|
EnterpriseChannelValidation.authenticateChannelToken = authenticateChannelToken;
|
|
/**
|
|
* Validate the ClaimsIdentity to ensure it came from the channel service.
|
|
*
|
|
* @param {ClaimsIdentity} identity The identity to validate
|
|
* @param {ICredentialProvider} credentials The user defined set of valid credentials, such as the AppId.
|
|
* @returns {Promise<ClaimsIdentity>} A valid ClaimsIdentity.
|
|
*/
|
|
function validateIdentity(identity, credentials) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!identity) {
|
|
// No valid identity. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized. No valid identity.', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
if (!identity.isAuthenticated) {
|
|
// The token is in some way invalid. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized. Is not authenticated', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
// Now check that the AppID in the claimset matches
|
|
// what we're looking for. Note that in a multi-tenant bot, this value
|
|
// comes from developer code that may be reaching out to a service, hence the
|
|
// Async validation.
|
|
// Look for the "aud" claim, but only if issued from the Bot Framework
|
|
if (identity.getClaimValue(authenticationConstants_1.AuthenticationConstants.IssuerClaim) !==
|
|
authenticationConstants_1.AuthenticationConstants.ToBotFromChannelTokenIssuer) {
|
|
// The relevant Audiance Claim MUST be present. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized. Issuer Claim MUST be present.', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
// The AppId from the claim in the token must match the AppId specified by the developer.
|
|
// In this case, the token is destined for the app, so we find the app ID in the audience claim.
|
|
const audClaim = identity.getClaimValue(authenticationConstants_1.AuthenticationConstants.AudienceClaim);
|
|
if (!(yield credentials.isValidAppId(audClaim || ''))) {
|
|
// The AppId is not valid or not present. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError(`Unauthorized. Invalid AppId passed on token: ${audClaim}`, botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
return identity;
|
|
});
|
|
}
|
|
EnterpriseChannelValidation.validateIdentity = validateIdentity;
|
|
})(EnterpriseChannelValidation = exports.EnterpriseChannelValidation || (exports.EnterpriseChannelValidation = {}));
|
|
//# sourceMappingURL=enterpriseChannelValidation.js.map
|