Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Skills] Use AuthenticationConfiguration #1470

Merged
merged 3 commits into from
Dec 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions libraries/botframework-connector/src/auth/channelValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
* Licensed under the MIT License.
*/
import { VerifyOptions } from 'jsonwebtoken';
import { ClaimsIdentity } from './claimsIdentity';
import { AuthenticationConstants } from './authenticationConstants';
import { AuthenticationConfiguration } from './authenticationConfiguration';
import { ClaimsIdentity } from './claimsIdentity';
import { ICredentialProvider } from './credentialProvider';
import { JwtTokenExtractor } from './jwtTokenExtractor';

Expand All @@ -31,16 +32,19 @@ export namespace ChannelValidation {
* @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 {string} channelId
* @param {AuthenticationConfiguration} authConfig
* @returns {Promise<ClaimsIdentity>} A valid ClaimsIdentity.
*/
export async function authenticateChannelTokenWithServiceUrl(
authHeader: string,
credentials: ICredentialProvider,
serviceUrl: string,
channelId: string
channelId: string,
authConfig: AuthenticationConfiguration = new AuthenticationConfiguration()
): Promise<ClaimsIdentity> {

const identity: ClaimsIdentity = await authenticateChannelToken(authHeader, credentials, channelId);
const identity: ClaimsIdentity = await authenticateChannelToken(authHeader, credentials, channelId, authConfig);

const serviceUrlClaim: string = identity.getClaimValue(AuthenticationConstants.ServiceUrlClaim);
if (serviceUrlClaim !== serviceUrl) {
Expand All @@ -56,20 +60,23 @@ export namespace ChannelValidation {
* 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} channelId
* @param {AuthenticationConfiguration} authConfig
* @returns {Promise<ClaimsIdentity>} A valid ClaimsIdentity.
*/
export async function authenticateChannelToken(
authHeader: string,
credentials: ICredentialProvider,
channelId: string
channelId: string,
authConfig: AuthenticationConfiguration = new AuthenticationConfiguration()
): Promise<ClaimsIdentity> {

const tokenExtractor: JwtTokenExtractor = new JwtTokenExtractor(
ToBotFromChannelTokenValidationParameters,
OpenIdMetadataEndpoint ? OpenIdMetadataEndpoint : AuthenticationConstants.ToBotFromChannelOpenIdMetadataUrl,
AuthenticationConstants.AllowedSigningAlgorithms);

const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId);
const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId, authConfig.requiredEndorsements);

return await validateIdentity(identity, credentials);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { decode, VerifyOptions } from 'jsonwebtoken';
import { ClaimsIdentity } from './claimsIdentity';
import { AuthenticationConstants } from './authenticationConstants';
import { AuthenticationConfiguration } from './authenticationConfiguration';
import { GovernmentConstants } from './governmentConstants';
import { ICredentialProvider } from './credentialProvider';
import { JwtTokenExtractor } from './jwtTokenExtractor';
Expand Down Expand Up @@ -95,13 +96,16 @@ export namespace EmulatorValidation {
* @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} channelService The channelService value that distinguishes public Azure from US Government Azure.
* @param {string} channelId
* @param {AuthenticationConfiguration} authConfig
* @returns {Promise<ClaimsIdentity>} A valid ClaimsIdentity.
*/
export async function authenticateEmulatorToken(
authHeader: string,
credentials: ICredentialProvider,
channelService: string,
channelId: string
channelId: string,
authConfig: AuthenticationConfiguration = new AuthenticationConfiguration()
): Promise<ClaimsIdentity> {
const openIdMetadataUrl = (channelService !== undefined && JwtTokenValidation.isGovernment(channelService)) ?
GovernmentConstants.ToBotFromEmulatorOpenIdMetadataUrl :
Expand All @@ -112,7 +116,7 @@ export namespace EmulatorValidation {
openIdMetadataUrl,
AuthenticationConstants.AllowedSigningAlgorithms);

const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId);
const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId, authConfig.requiredEndorsements);
if (!identity) {
// No valid identity. Not Authorized.
throw new Error('Unauthorized. No valid identity.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
* Licensed under the MIT License.
*/
import { VerifyOptions } from 'jsonwebtoken';
import { AuthenticationConfiguration } from './authenticationConfiguration';
import { AuthenticationConstants } from './authenticationConstants';
import { ChannelValidation } from './channelValidation';
import { ClaimsIdentity } from './claimsIdentity';
import { AuthenticationConstants } from './authenticationConstants';
import { ICredentialProvider } from './credentialProvider';
import { JwtTokenExtractor } from './jwtTokenExtractor';

Expand Down Expand Up @@ -62,7 +63,8 @@ export namespace EnterpriseChannelValidation {
authHeader: string,
credentials: ICredentialProvider,
channelId: string,
channelService: string
channelService: string,
authConfig: AuthenticationConfiguration = new AuthenticationConfiguration()
): Promise<ClaimsIdentity> {

const tokenExtractor: JwtTokenExtractor = new JwtTokenExtractor(
Expand All @@ -72,7 +74,7 @@ export namespace EnterpriseChannelValidation {
AuthenticationConstants.ToBotFromEnterpriseChannelOpenIdMetadataUrlFormat.replace('{channelService}', channelService),
AuthenticationConstants.AllowedSigningAlgorithms);

const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId);
const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId, authConfig.requiredEndorsements);

return await validateIdentity(identity, credentials);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
* Licensed under the MIT License.
*/
import { VerifyOptions } from 'jsonwebtoken';
import { ClaimsIdentity } from './claimsIdentity';
import { AuthenticationConfiguration } from './authenticationConfiguration';
import { AuthenticationConstants } from './authenticationConstants';
import { ClaimsIdentity } from './claimsIdentity';
import { ICredentialProvider } from './credentialProvider';
import { GovernmentConstants } from './governmentConstants';
import { JwtTokenExtractor } from './jwtTokenExtractor';
Expand Down Expand Up @@ -57,12 +58,15 @@ export namespace GovernmentChannelValidation {
* 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} channelId
* @param {AuthenticationConfiguration} authConfig
* @returns {Promise<ClaimsIdentity>} A valid ClaimsIdentity.
*/
export async function authenticateChannelToken(
authHeader: string,
credentials: ICredentialProvider,
channelId: string
channelId: string,
authConfig: AuthenticationConfiguration = new AuthenticationConfiguration()
): Promise<ClaimsIdentity> {

const tokenExtractor: JwtTokenExtractor = new JwtTokenExtractor(
Expand All @@ -71,7 +75,7 @@ export namespace GovernmentChannelValidation {
OpenIdMetadataEndpoint : GovernmentConstants.ToBotFromChannelOpenIdMetadataUrl,
AuthenticationConstants.AllowedSigningAlgorithms);

const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId);
const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader(authHeader, channelId, authConfig.requiredEndorsements);

return await validateIdentity(identity, credentials);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ export class JwtTokenExtractor {
return null;
}

public async getIdentity(scheme: string, parameter: string, channelId: string, requiredEndorsements: string[]): Promise<ClaimsIdentity | null> {
if (!requiredEndorsements) {
throw new Error('JwtTokenExtractor.getIdentity() must be called valid a requiredEndorsements parameter');
}
public async getIdentity(scheme: string, parameter: string, channelId: string, requiredEndorsements: string[] = []): Promise<ClaimsIdentity | null> {

// No header in correct scheme or no token
if (scheme !== 'Bearer' || !parameter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,9 @@ export namespace JwtTokenValidation {
channelService: string,
channelId: string,
serviceUrl: string = '',
authConfig?: AuthenticationConfiguration
authConfig: AuthenticationConfiguration = new AuthenticationConfiguration()
): Promise<ClaimsIdentity> {
if (!authHeader.trim()) { throw new Error('\'authHeader\' required.'); }
if (!authConfig) {
authConfig = new AuthenticationConfiguration();
}

const identity = await authenticateToken(authHeader, credentials, channelService, channelId, authConfig, serviceUrl);

Expand Down