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

BuiltinBotFrameworkAuthentication.GetAppId try to check (appid/azp) before (aud) #6724

Closed
wants to merge 8 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -140,52 +140,13 @@ public static async Task<ClaimsIdentity> AuthenticateAseTokenAsync(string authHe
{
// The token is in some way invalid. Not Authorized.
throw new UnauthorizedAccessException("Token Not Authenticated");
}

// 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.
Claim versionClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.VersionClaim);
if (versionClaim == null)
{
throw new UnauthorizedAccessException("'ver' claim is required on AseChannel Tokens.");
}
}

string tokenVersion = versionClaim.Value;
string appID = string.Empty;
var appID = JwtTokenValidation.GetAppIdFromClaims(identity.Claims);

// The AseChannel, depending on Version, sends the AppId via either the
// appid claim (Version 1) or the Authorized Party claim (Version 2).
if (string.IsNullOrWhiteSpace(tokenVersion) || tokenVersion == "1.0")
{
// either no Version or a version of "1.0" means we should look for
// the claim in the "appid" claim.
Claim appIdClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.AppIdClaim);
if (appIdClaim == null)
{
// No claim around AppID. Not Authorized.
throw new UnauthorizedAccessException("'appid' claim is required on AseChannel Token version '1.0'.");
}

appID = appIdClaim.Value;
}
else if (tokenVersion == "2.0")
{
// AseChannel, "2.0" puts the AppId in the "azp" claim.
Claim appZClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.AuthorizedParty);
if (appZClaim == null)
{
// No claim around AppID. Not Authorized.
throw new UnauthorizedAccessException("'azp' claim is required on AseChannel Token version '2.0'.");
}

appID = appZClaim.Value;
}
else
if (string.IsNullOrEmpty(appID))
{
// Unknown Version. Not Authorized.
throw new UnauthorizedAccessException($"Unknown AseChannel Token version '{tokenVersion}'.");
throw new UnauthorizedAccessException("appid or azp claim is required in Token");
}

if (!await _credentialProvider.IsValidAppIdAsync(appID).ConfigureAwait(false))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,17 @@ protected BuiltinBotFrameworkAuthentication(string toChannelFromBotOAuthScope, s

public static string GetAppId(ClaimsIdentity claimsIdentity)
{
// 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.
var botAppIdClaim = claimsIdentity.Claims?.SingleOrDefault(claim => claim.Type == AuthenticationConstants.AudienceClaim);
if (botAppIdClaim == null)
var appId = JwtTokenValidation.GetAppIdFromClaims(claimsIdentity.Claims);

if (string.IsNullOrEmpty(appId))
{
botAppIdClaim = claimsIdentity.Claims?.SingleOrDefault(claim => claim.Type == AuthenticationConstants.AppIdClaim);
// 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.
appId = claimsIdentity.Claims?.SingleOrDefault(claim => claim.Type == AuthenticationConstants.AudienceClaim)?.Value;
}

return botAppIdClaim?.Value;
return appId;
}

public override string GetOriginatingAudience()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,50 +153,11 @@ public static async Task<ClaimsIdentity> AuthenticateEmulatorToken(string authHe
throw new UnauthorizedAccessException("Token Not Authenticated");
}

// 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.
Claim versionClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.VersionClaim);
if (versionClaim == null)
{
throw new UnauthorizedAccessException("'ver' claim is required on Emulator Tokens.");
}

string tokenVersion = versionClaim.Value;
string appID = string.Empty;

// The Emulator, depending on Version, sends the AppId via either the
// appid claim (Version 1) or the Authorized Party claim (Version 2).
if (string.IsNullOrWhiteSpace(tokenVersion) || tokenVersion == "1.0")
{
// either no Version or a version of "1.0" means we should look for
// the claim in the "appid" claim.
Claim appIdClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.AppIdClaim);
if (appIdClaim == null)
{
// No claim around AppID. Not Authorized.
throw new UnauthorizedAccessException("'appid' claim is required on Emulator Token version '1.0'.");
}
var appID = JwtTokenValidation.GetAppIdFromClaims(identity.Claims);

appID = appIdClaim.Value;
}
else if (tokenVersion == "2.0")
{
// Emulator, "2.0" puts the AppId in the "azp" claim.
Claim appZClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.AuthorizedParty);
if (appZClaim == null)
{
// No claim around AppID. Not Authorized.
throw new UnauthorizedAccessException("'azp' claim is required on Emulator Token version '2.0'.");
}

appID = appZClaim.Value;
}
else
if (string.IsNullOrEmpty(appID))
{
// Unknown Version. Not Authorized.
throw new UnauthorizedAccessException($"Unknown Emulator Token version '{tokenVersion}'.");
throw new UnauthorizedAccessException("appid or azp claim is required in Token");
}

if (!await credentials.IsValidAppIdAsync(appID).ConfigureAwait(false))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,50 +334,11 @@ private async Task<ClaimsIdentity> EmulatorValidation_AuthenticateEmulatorTokenA
throw new UnauthorizedAccessException("Token Not Authenticated");
}

// 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.
Claim versionClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.VersionClaim);
if (versionClaim == null)
{
throw new UnauthorizedAccessException("'ver' claim is required on Emulator Tokens.");
}

string tokenVersion = versionClaim.Value;
string appID = string.Empty;

// The Emulator, depending on Version, sends the AppId via either the
// appid claim (Version 1) or the Authorized Party claim (Version 2).
if (string.IsNullOrWhiteSpace(tokenVersion) || tokenVersion == "1.0")
{
// either no Version or a version of "1.0" means we should look for
// the claim in the "appid" claim.
Claim appIdClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.AppIdClaim);
if (appIdClaim == null)
{
// No claim around AppID. Not Authorized.
throw new UnauthorizedAccessException("'appid' claim is required on Emulator Token version '1.0'.");
}
var appID = JwtTokenValidation.GetAppIdFromClaims(identity.Claims);

appID = appIdClaim.Value;
}
else if (tokenVersion == "2.0")
{
// Emulator, "2.0" puts the AppId in the "azp" claim.
Claim appZClaim = identity.Claims.FirstOrDefault(c => c.Type == AuthenticationConstants.AuthorizedParty);
if (appZClaim == null)
{
// No claim around AppID. Not Authorized.
throw new UnauthorizedAccessException("'azp' claim is required on Emulator Token version '2.0'.");
}

appID = appZClaim.Value;
}
else
if (string.IsNullOrEmpty(appID))
{
// Unknown Version. Not Authorized.
throw new UnauthorizedAccessException($"Unknown Emulator Token version '{tokenVersion}'.");
throw new UnauthorizedAccessException("appid or azp claim is required in Token");
}

if (!await _credentialsFactory.IsValidAppIdAsync(appID, cancellationToken).ConfigureAwait(false))
Expand Down
Loading