Browse Source

Update the TypeValidator custom delegate to avoid throwing when the JWT token has no "typ" header but contains a "token_usage" claim

pull/1020/head
Kévin Chalet 6 years ago
parent
commit
682af18392
  1. 2
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  2. 14
      src/OpenIddict.Server/OpenIddictServerOptions.cs
  3. 2
      src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
  4. 14
      src/OpenIddict.Validation/OpenIddictValidationOptions.cs

2
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -451,7 +451,7 @@ namespace OpenIddict.Server
{ {
// If no specific token type is expected, accept all token types at this stage. // If no specific token type is expected, accept all token types at this stage.
// Additional filtering can be made based on the resolved/actual token type. // Additional filtering can be made based on the resolved/actual token type.
var type when string.IsNullOrEmpty(type) => Array.Empty<string>(), var type when string.IsNullOrEmpty(type) => null,
// For access tokens, both "at+jwt" and "application/at+jwt" are valid. // For access tokens, both "at+jwt" and "application/at+jwt" are valid.
TokenTypeHints.AccessToken => new[] TokenTypeHints.AccessToken => new[]

14
src/OpenIddict.Server/OpenIddictServerOptions.cs

@ -121,11 +121,6 @@ namespace OpenIddict.Server
// This validator overrides the default logic used by IdentityModel to resolve the type from this claim. // This validator overrides the default logic used by IdentityModel to resolve the type from this claim.
TypeValidator = (type, token, parameters) => TypeValidator = (type, token, parameters) =>
{ {
if (string.IsNullOrEmpty(type))
{
throw new SecurityTokenInvalidTypeException("The 'typ' header of the JWT token cannot be null or empty.");
}
// If available, try to resolve the actual type from the "token_usage" claim. // If available, try to resolve the actual type from the "token_usage" claim.
if (((JsonWebToken) token).TryGetPayloadValue(OpenIddictConstants.Claims.TokenUsage, out string usage)) if (((JsonWebToken) token).TryGetPayloadValue(OpenIddictConstants.Claims.TokenUsage, out string usage))
{ {
@ -138,7 +133,14 @@ namespace OpenIddict.Server
}; };
} }
// Unlike IdentityModel, this custom validator deliberately uses case-insensitive comparisons. // At this point, throw an exception if the type cannot be resolved from the "typ" header
// (provided via the type delegate parameter) or inferred from the token_usage claim.
if (string.IsNullOrEmpty(type))
{
throw new SecurityTokenInvalidTypeException("The type of the JWT token cannot be resolved or inferred.");
}
// Note: unlike IdentityModel, this custom validator deliberately uses case-insensitive comparisons.
if (parameters.ValidTypes != null && parameters.ValidTypes.Any() && if (parameters.ValidTypes != null && parameters.ValidTypes.Any() &&
!parameters.ValidTypes.Contains(type, StringComparer.OrdinalIgnoreCase)) !parameters.ValidTypes.Contains(type, StringComparer.OrdinalIgnoreCase))
{ {

2
src/OpenIddict.Validation/OpenIddictValidationHandlers.cs

@ -238,7 +238,7 @@ namespace OpenIddict.Validation
{ {
// If no specific token type is expected, accept all token types at this stage. // If no specific token type is expected, accept all token types at this stage.
// Additional filtering can be made based on the resolved/actual token type. // Additional filtering can be made based on the resolved/actual token type.
var type when string.IsNullOrEmpty(type) => Array.Empty<string>(), var type when string.IsNullOrEmpty(type) => null,
// For access tokens, both "at+jwt" and "application/at+jwt" are valid. // For access tokens, both "at+jwt" and "application/at+jwt" are valid.
TokenTypeHints.AccessToken => new[] TokenTypeHints.AccessToken => new[]

14
src/OpenIddict.Validation/OpenIddictValidationOptions.cs

@ -118,11 +118,6 @@ namespace OpenIddict.Validation
// This validator overrides the default logic used by IdentityModel to resolve the type from this claim. // This validator overrides the default logic used by IdentityModel to resolve the type from this claim.
TypeValidator = (type, token, parameters) => TypeValidator = (type, token, parameters) =>
{ {
if (string.IsNullOrEmpty(type))
{
throw new SecurityTokenInvalidTypeException("The 'typ' header of the JWT token cannot be null or empty.");
}
// If available, try to resolve the actual type from the "token_usage" claim. // If available, try to resolve the actual type from the "token_usage" claim.
if (((JsonWebToken) token).TryGetPayloadValue(Claims.TokenUsage, out string usage)) if (((JsonWebToken) token).TryGetPayloadValue(Claims.TokenUsage, out string usage))
{ {
@ -135,7 +130,14 @@ namespace OpenIddict.Validation
}; };
} }
// Unlike IdentityModel, this custom validator deliberately uses case-insensitive comparisons. // At this point, throw an exception if the type cannot be resolved from the "typ" header
// (provided via the type delegate parameter) or inferred from the token_usage claim.
if (string.IsNullOrEmpty(type))
{
throw new SecurityTokenInvalidTypeException("The type of the JWT token cannot be resolved or inferred.");
}
// Note: unlike IdentityModel, this custom validator deliberately uses case-insensitive comparisons.
if (parameters.ValidTypes != null && parameters.ValidTypes.Any() && if (parameters.ValidTypes != null && parameters.ValidTypes.Any() &&
!parameters.ValidTypes.Contains(type, StringComparer.OrdinalIgnoreCase)) !parameters.ValidTypes.Contains(type, StringComparer.OrdinalIgnoreCase))
{ {

Loading…
Cancel
Save