385 lines
No EOL
25 KiB
JavaScript
385 lines
No EOL
25 KiB
JavaScript
"use strict";
|
|
// Copyright (c) Microsoft Corporation.
|
|
// 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.ParameterizedBotFrameworkAuthentication = void 0;
|
|
const botframework_schema_1 = require("botframework-schema");
|
|
const authenticationConstants_1 = require("./authenticationConstants");
|
|
const authenticationError_1 = require("./authenticationError");
|
|
const botFrameworkAuthentication_1 = require("./botFrameworkAuthentication");
|
|
const connectorFactoryImpl_1 = require("./connectorFactoryImpl");
|
|
const botFrameworkClientImpl_1 = require("./botFrameworkClientImpl");
|
|
const claimsIdentity_1 = require("./claimsIdentity");
|
|
const emulatorValidation_1 = require("./emulatorValidation");
|
|
const jwtTokenExtractor_1 = require("./jwtTokenExtractor");
|
|
const jwtTokenValidation_1 = require("./jwtTokenValidation");
|
|
const skillValidation_1 = require("./skillValidation");
|
|
const tokenValidationParameters_1 = require("./tokenValidationParameters");
|
|
const userTokenClientImpl_1 = require("./userTokenClientImpl");
|
|
const aseChannelValidation_1 = require("./aseChannelValidation");
|
|
function getAppId(claimsIdentity) {
|
|
var _a, _b;
|
|
// For requests from channel App Id is in Audience claim of JWT token. For emulator it is in AppId claim. For
|
|
// unauthenticated requests we have anonymous claimsIdentity provided auth is disabled.
|
|
// For Activities coming from Emulator AppId claim contains the Bot's AAD AppId.
|
|
return ((_b = (_a = claimsIdentity.getClaimValue(authenticationConstants_1.AuthenticationConstants.AudienceClaim)) !== null && _a !== void 0 ? _a : claimsIdentity.getClaimValue(authenticationConstants_1.AuthenticationConstants.AppIdClaim)) !== null && _b !== void 0 ? _b : undefined);
|
|
}
|
|
/**
|
|
* @internal
|
|
* Parameterized [BotFrameworkAuthentication](xref:botframework-connector.BotFrameworkAuthentication) used to authenticate Bot Framework Protocol network calls within this environment.
|
|
*/
|
|
class ParameterizedBotFrameworkAuthentication extends botFrameworkAuthentication_1.BotFrameworkAuthentication {
|
|
/**
|
|
* @param validateAuthority The validate authority value to use.
|
|
* @param toChannelFromBotLoginUrl The to Channel from bot login url.
|
|
* @param toChannelFromBotOAuthScope The to Channel from bot oauth scope.
|
|
* @param toBotFromChannelTokenIssuer The to bot from Channel Token Issuer.
|
|
* @param oAuthUrl The OAuth url.
|
|
* @param toBotFromChannelOpenIdMetadataUrl The to bot from Channel Open Id Metadata url.
|
|
* @param toBotFromEmulatorOpenIdMetadataUrl The to bot from Emulator Open Id Metadata url.
|
|
* @param callerId The callerId set on an authenticated [Activities](xref:botframework-schema.Activity).
|
|
* @param credentialsFactory The [ServiceClientCredentialsFactory](xref:botframework-connector.ServiceClientCredentialsFactory) to use to create credentials.
|
|
* @param authConfiguration The [AuthenticationConfiguration](xref:botframework-connector.AuthenticationConfiguration) to use.
|
|
* @param botFrameworkClientFetch The fetch to use in BotFrameworkClient.
|
|
* @param connectorClientOptions The [ConnectorClientOptions](xref:botframework-connector.ConnectorClientOptions) to use when creating ConnectorClients.
|
|
*/
|
|
constructor(validateAuthority, toChannelFromBotLoginUrl, toChannelFromBotOAuthScope, toBotFromChannelTokenIssuer, oAuthUrl, toBotFromChannelOpenIdMetadataUrl, toBotFromEmulatorOpenIdMetadataUrl, callerId, credentialsFactory, authConfiguration, botFrameworkClientFetch, connectorClientOptions = {}) {
|
|
super();
|
|
this.validateAuthority = validateAuthority;
|
|
this.toChannelFromBotLoginUrl = toChannelFromBotLoginUrl;
|
|
this.toChannelFromBotOAuthScope = toChannelFromBotOAuthScope;
|
|
this.toBotFromChannelTokenIssuer = toBotFromChannelTokenIssuer;
|
|
this.oAuthUrl = oAuthUrl;
|
|
this.toBotFromChannelOpenIdMetadataUrl = toBotFromChannelOpenIdMetadataUrl;
|
|
this.toBotFromEmulatorOpenIdMetadataUrl = toBotFromEmulatorOpenIdMetadataUrl;
|
|
this.callerId = callerId;
|
|
this.credentialsFactory = credentialsFactory;
|
|
this.authConfiguration = authConfiguration;
|
|
this.botFrameworkClientFetch = botFrameworkClientFetch;
|
|
this.connectorClientOptions = connectorClientOptions;
|
|
}
|
|
/**
|
|
* Gets the originating audience from Bot OAuth scope.
|
|
*
|
|
* @returns The originating audience.
|
|
*/
|
|
getOriginatingAudience() {
|
|
return this.toChannelFromBotOAuthScope;
|
|
}
|
|
/**
|
|
* @param authHeader The http auth header received in the skill request.
|
|
* @returns The identity validation result.
|
|
*/
|
|
authenticateChannelRequest(authHeader) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!authHeader.trim()) {
|
|
const isAuthDisabled = yield this.credentialsFactory.isAuthenticationDisabled();
|
|
if (!isAuthDisabled) {
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized Access. Request is not authorized', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
// In the scenario where auth is disabled, we still want to have the isAuthenticated flag set in the
|
|
// ClaimsIdentity. To do this requires adding in an empty claim. Since ChannelServiceHandler calls are
|
|
// always a skill callback call, we set the skill claim too.
|
|
return skillValidation_1.SkillValidation.createAnonymousSkillClaim();
|
|
}
|
|
return this.JwtTokenValidation_validateAuthHeader(authHeader, 'unknown', null);
|
|
});
|
|
}
|
|
/**
|
|
* Validate Bot Framework Protocol requests.
|
|
*
|
|
* @param activity The inbound Activity.
|
|
* @param authHeader The http auth header received in the skill request.
|
|
* @returns Promise with AuthenticateRequestResult.
|
|
*/
|
|
authenticateRequest(activity, authHeader) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const claimsIdentity = yield this.JwtTokenValidation_authenticateRequest(activity, authHeader);
|
|
const outboundAudience = skillValidation_1.SkillValidation.isSkillClaim(claimsIdentity.claims)
|
|
? jwtTokenValidation_1.JwtTokenValidation.getAppIdFromClaims(claimsIdentity.claims)
|
|
: this.toChannelFromBotOAuthScope;
|
|
const callerId = yield this.generateCallerId(this.credentialsFactory, claimsIdentity, this.callerId);
|
|
const connectorFactory = new connectorFactoryImpl_1.ConnectorFactoryImpl(getAppId(claimsIdentity), this.toChannelFromBotOAuthScope, this.toChannelFromBotLoginUrl, this.validateAuthority, this.credentialsFactory, this.connectorClientOptions);
|
|
return {
|
|
audience: outboundAudience,
|
|
callerId,
|
|
claimsIdentity,
|
|
connectorFactory,
|
|
};
|
|
});
|
|
}
|
|
/**
|
|
* Validate Bot Framework Protocol requests.
|
|
*
|
|
* @param authHeader The http auth header received in the skill request.
|
|
* @param channelIdHeader The channel Id HTTP header.
|
|
* @returns Promise with AuthenticateRequestResult.
|
|
*/
|
|
authenticateStreamingRequest(authHeader, channelIdHeader) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!(channelIdHeader === null || channelIdHeader === void 0 ? void 0 : channelIdHeader.trim()) && !(yield this.credentialsFactory.isAuthenticationDisabled())) {
|
|
throw new authenticationError_1.AuthenticationError("'channelIdHeader' required.", botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
const claimsIdentity = yield this.JwtTokenValidation_validateAuthHeader(authHeader, channelIdHeader, null);
|
|
const outboundAudience = skillValidation_1.SkillValidation.isSkillClaim(claimsIdentity.claims)
|
|
? jwtTokenValidation_1.JwtTokenValidation.getAppIdFromClaims(claimsIdentity.claims)
|
|
: this.toChannelFromBotOAuthScope;
|
|
const callerId = yield this.generateCallerId(this.credentialsFactory, claimsIdentity, this.callerId);
|
|
return { audience: outboundAudience, callerId, claimsIdentity };
|
|
});
|
|
}
|
|
/**
|
|
* Creates the appropriate UserTokenClient instance.
|
|
*
|
|
* @param claimsIdentity The inbound Activity's ClaimsIdentity.
|
|
* @returns Promise with UserTokenClient instance.
|
|
*/
|
|
createUserTokenClient(claimsIdentity) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const appId = getAppId(claimsIdentity);
|
|
const credentials = yield this.credentialsFactory.createCredentials(appId, this.toChannelFromBotOAuthScope, this.toChannelFromBotLoginUrl, this.validateAuthority);
|
|
return new userTokenClientImpl_1.UserTokenClientImpl(appId, credentials, this.oAuthUrl, this.connectorClientOptions);
|
|
});
|
|
}
|
|
/**
|
|
* 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.
|
|
*/
|
|
createConnectorFactory(claimsIdentity) {
|
|
return new connectorFactoryImpl_1.ConnectorFactoryImpl(getAppId(claimsIdentity), this.toChannelFromBotOAuthScope, this.toChannelFromBotLoginUrl, this.validateAuthority, this.credentialsFactory, this.connectorClientOptions);
|
|
}
|
|
/**
|
|
* Creates a BotFrameworkClient used for calling Skills.
|
|
*
|
|
* @returns A BotFrameworkClient instance to call Skills.
|
|
*/
|
|
createBotFrameworkClient() {
|
|
return new botFrameworkClientImpl_1.BotFrameworkClientImpl(this.credentialsFactory, this.toChannelFromBotLoginUrl, this.botFrameworkClientFetch, this.connectorClientOptions);
|
|
}
|
|
JwtTokenValidation_authenticateRequest(activity, authHeader) {
|
|
var _a;
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!authHeader.trim()) {
|
|
const isAuthDisabled = yield this.credentialsFactory.isAuthenticationDisabled();
|
|
if (!isAuthDisabled) {
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized Access. Request is not authorized', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
// Check if the activity is for a skill call and is coming from the Emulator.
|
|
if (activity.channelId === botframework_schema_1.Channels.Emulator && ((_a = activity.recipient) === null || _a === void 0 ? void 0 : _a.role) === botframework_schema_1.RoleTypes.Skill) {
|
|
return skillValidation_1.SkillValidation.createAnonymousSkillClaim();
|
|
}
|
|
// In the scenario where Auth is disabled, we still want to have the
|
|
// IsAuthenticated flag set in the ClaimsIdentity. To do this requires
|
|
// adding in an empty claim.
|
|
return new claimsIdentity_1.ClaimsIdentity([], authenticationConstants_1.AuthenticationConstants.AnonymousAuthType);
|
|
}
|
|
const claimsIdentity = yield this.JwtTokenValidation_validateAuthHeader(authHeader, activity.channelId, activity.serviceUrl);
|
|
return claimsIdentity;
|
|
});
|
|
}
|
|
JwtTokenValidation_validateAuthHeader(authHeader, channelId, serviceUrl = '') {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const identity = yield this.JwtTokenValidation_authenticateToken(authHeader, channelId, serviceUrl);
|
|
yield this.JwtTokenValidation_validateClaims(identity.claims);
|
|
return identity;
|
|
});
|
|
}
|
|
JwtTokenValidation_validateClaims(claims = []) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (this.authConfiguration.validateClaims) {
|
|
// Call the validation method if defined (it should throw an exception if the validation fails)
|
|
yield this.authConfiguration.validateClaims(claims);
|
|
}
|
|
else if (skillValidation_1.SkillValidation.isSkillClaim(claims)) {
|
|
// Skill claims must be validated using AuthenticationConfiguration validateClaims
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized Access. Request is not authorized. Skill Claims require validation.', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
});
|
|
}
|
|
JwtTokenValidation_authenticateToken(authHeader, channelId, serviceUrl) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (aseChannelValidation_1.AseChannelValidation.isTokenFromAseChannel(channelId)) {
|
|
return aseChannelValidation_1.AseChannelValidation.authenticateAseChannelToken(authHeader);
|
|
}
|
|
if (skillValidation_1.SkillValidation.isSkillToken(authHeader)) {
|
|
return this.SkillValidation_authenticateChannelToken(authHeader, channelId);
|
|
}
|
|
if (emulatorValidation_1.EmulatorValidation.isTokenFromEmulator(authHeader)) {
|
|
return this.EmulatorValidation_authenticateEmulatorToken(authHeader, channelId);
|
|
}
|
|
// Handle requests from BotFramework Channels
|
|
return this.ChannelValidation_authenticateChannelToken(authHeader, serviceUrl, channelId);
|
|
});
|
|
}
|
|
SkillValidation_authenticateChannelToken(authHeader, channelId) {
|
|
var _a, _b;
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
// Add allowed token issuers from configuration.
|
|
const verifyOptions = Object.assign(Object.assign({}, tokenValidationParameters_1.ToBotFromBotOrEmulatorTokenValidationParameters), { issuer: [
|
|
...tokenValidationParameters_1.ToBotFromBotOrEmulatorTokenValidationParameters.issuer,
|
|
...((_a = this.authConfiguration.validTokenIssuers) !== null && _a !== void 0 ? _a : []),
|
|
] });
|
|
const tokenExtractor = new jwtTokenExtractor_1.JwtTokenExtractor(verifyOptions, this.toBotFromEmulatorOpenIdMetadataUrl, authenticationConstants_1.AuthenticationConstants.AllowedSigningAlgorithms, (_b = this.connectorClientOptions) === null || _b === void 0 ? void 0 : _b.proxySettings);
|
|
const parts = authHeader.split(' ');
|
|
const identity = yield tokenExtractor.getIdentity(parts[0], parts[1], channelId, this.authConfiguration.requiredEndorsements);
|
|
yield this.SkillValidation_ValidateIdentity(identity);
|
|
return identity;
|
|
});
|
|
}
|
|
SkillValidation_ValidateIdentity(identity) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!identity) {
|
|
// No valid identity. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('SkillValidation.validateIdentity(): Invalid identity', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
if (!identity.isAuthenticated) {
|
|
// The token is in some way invalid. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('SkillValidation.validateIdentity(): Token not authenticated', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
const versionClaim = identity.getClaimValue(authenticationConstants_1.AuthenticationConstants.VersionClaim);
|
|
if (!versionClaim) {
|
|
// No version claim
|
|
throw new authenticationError_1.AuthenticationError(`SkillValidation.validateIdentity(): '${authenticationConstants_1.AuthenticationConstants.VersionClaim}' claim is required on skill Tokens.`, botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
// Look for the "aud" claim, but only if issued from the Bot Framework
|
|
const audienceClaim = identity.getClaimValue(authenticationConstants_1.AuthenticationConstants.AudienceClaim);
|
|
if (!audienceClaim) {
|
|
// Claim is not present or doesn't have a value. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError(`SkillValidation.validateIdentity(): '${authenticationConstants_1.AuthenticationConstants.AudienceClaim}' claim is required on skill Tokens.`, botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
if (!(yield this.credentialsFactory.isValidAppId(audienceClaim))) {
|
|
// The AppId is not valid. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('SkillValidation.validateIdentity(): Invalid audience.', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
const appId = jwtTokenValidation_1.JwtTokenValidation.getAppIdFromClaims(identity.claims);
|
|
if (!appId) {
|
|
// Invalid appId
|
|
throw new authenticationError_1.AuthenticationError('SkillValidation.validateIdentity(): Invalid appId.', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
});
|
|
}
|
|
EmulatorValidation_authenticateEmulatorToken(authHeader, channelId) {
|
|
var _a, _b;
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
// Add allowed token issuers from configuration.
|
|
const verifyOptions = Object.assign(Object.assign({}, tokenValidationParameters_1.ToBotFromBotOrEmulatorTokenValidationParameters), { issuer: [
|
|
...tokenValidationParameters_1.ToBotFromBotOrEmulatorTokenValidationParameters.issuer,
|
|
...((_a = this.authConfiguration.validTokenIssuers) !== null && _a !== void 0 ? _a : []),
|
|
] });
|
|
const tokenExtractor = new jwtTokenExtractor_1.JwtTokenExtractor(verifyOptions, this.toBotFromEmulatorOpenIdMetadataUrl, authenticationConstants_1.AuthenticationConstants.AllowedSigningAlgorithms, (_b = this.connectorClientOptions) === null || _b === void 0 ? void 0 : _b.proxySettings);
|
|
const identity = yield tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId, this.authConfiguration.requiredEndorsements);
|
|
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.
|
|
const versionClaim = identity.getClaimValue(authenticationConstants_1.AuthenticationConstants.VersionClaim);
|
|
if (versionClaim === null) {
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized. "ver" claim is required on Emulator Tokens.', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
let appId = '';
|
|
// The Emulator, depending on Version, sends the AppId via either the
|
|
// appid claim (Version 1) or the Authorized Party claim (Version 2).
|
|
if (!versionClaim || versionClaim === '1.0') {
|
|
// either no Version or a version of "1.0" means we should look for
|
|
// the claim in the "appid" claim.
|
|
const appIdClaim = identity.getClaimValue(authenticationConstants_1.AuthenticationConstants.AppIdClaim);
|
|
if (!appIdClaim) {
|
|
// No claim around AppID. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized. "appid" claim is required on Emulator Token version "1.0".', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
appId = appIdClaim;
|
|
}
|
|
else if (versionClaim === '2.0') {
|
|
// Emulator, "2.0" puts the AppId in the "azp" claim.
|
|
const appZClaim = identity.getClaimValue(authenticationConstants_1.AuthenticationConstants.AuthorizedParty);
|
|
if (!appZClaim) {
|
|
// No claim around AppID. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError('Unauthorized. "azp" claim is required on Emulator Token version "2.0".', botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
appId = appZClaim;
|
|
}
|
|
else {
|
|
// Unknown Version. Not Authorized.
|
|
throw new authenticationError_1.AuthenticationError(`Unauthorized. Unknown Emulator Token version "${versionClaim}".`, botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
if (!(yield this.credentialsFactory.isValidAppId(appId))) {
|
|
throw new authenticationError_1.AuthenticationError(`Unauthorized. Invalid AppId passed on token: ${appId}`, botframework_schema_1.StatusCodes.UNAUTHORIZED);
|
|
}
|
|
return identity;
|
|
});
|
|
}
|
|
ChannelValidation_authenticateChannelToken(authHeader, serviceUrl, channelId) {
|
|
var _a;
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const tokenValidationParameters = this.ChannelValidation_GetTokenValidationParameters();
|
|
const tokenExtractor = new jwtTokenExtractor_1.JwtTokenExtractor(tokenValidationParameters, this.toBotFromChannelOpenIdMetadataUrl, authenticationConstants_1.AuthenticationConstants.AllowedSigningAlgorithms, (_a = this.connectorClientOptions) === null || _a === void 0 ? void 0 : _a.proxySettings);
|
|
const identity = yield tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId, this.authConfiguration.requiredEndorsements);
|
|
return this.governmentChannelValidation_ValidateIdentity(identity, serviceUrl);
|
|
});
|
|
}
|
|
ChannelValidation_GetTokenValidationParameters() {
|
|
return {
|
|
issuer: [this.toBotFromChannelTokenIssuer],
|
|
audience: undefined,
|
|
clockTolerance: 5 * 60,
|
|
ignoreExpiration: false,
|
|
};
|
|
}
|
|
governmentChannelValidation_ValidateIdentity(identity, serviceUrl) {
|
|
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) !== this.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 this.credentialsFactory.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);
|
|
}
|
|
if (serviceUrl) {
|
|
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;
|
|
});
|
|
}
|
|
}
|
|
exports.ParameterizedBotFrameworkAuthentication = ParameterizedBotFrameworkAuthentication;
|
|
//# sourceMappingURL=parameterizedBotFrameworkAuthentication.js.map
|