Browse Source

Reject token requests containing a code_verifier when no code_challenge is attached to the authorization code

pull/904/head
Drew Fleming 6 years ago
committed by Kévin Chalet
parent
commit
78d14adb33
  1. 17
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  2. 40
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs

17
src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs

@ -1611,9 +1611,24 @@ namespace OpenIddict.Server
// is active even if the degraded mode is enabled and ensures that a code_verifier is sent if a
// code_challenge was stored in the authorization code when the authorization request was handled.
// Validate that the token request did not include the code_verifier parameter if the
// authorization request was not provided with both code_challenge and code_challenge_method.
var challenge = context.Principal.GetClaim(Claims.Private.CodeChallenge);
if (!string.IsNullOrEmpty(context.Request.CodeVerifier) && string.IsNullOrEmpty(challenge))
{
context.Logger.LogError("The token request was rejected because a 'code_verifier' " +
"parameter was presented but 'code_challenge' and/or 'code_challenge_method' " +
"was not a part of the authorization request.");
context.Reject(
error: Errors.InvalidRequest,
description: "The 'code_verifier' parameter is uncalled for in this request.");
return default;
}
// If a code challenge was initially sent in the authorization request and associated with the
// code, validate the code verifier to ensure the token request is sent by a legit caller.
var challenge = context.Principal.GetClaim(Claims.Private.CodeChallenge);
if (string.IsNullOrEmpty(challenge))
{
return default;

40
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs

@ -562,6 +562,46 @@ namespace OpenIddict.Server.FunctionalTests
"redirection endpoint the authorization code was initially sent to.", response.ErrorDescription);
}
[Fact]
public async Task ValidateTokenRequest_RequestCausesErrorWhenSendingCodeVerifier()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
.SetClaim(Claims.Subject, "Bob le Bricoleur");
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
});
// Act
var response = await client.PostAsync("/connect/token", new OpenIddictRequest
{
ClientId = "Fabrikam",
Code = "SplxlOBeZQQYbYS6WxSbIA",
CodeVerifier = "AbCd97394879834759873497549237098273498072304987523948673248972349857982345",
GrantType = GrantTypes.AuthorizationCode
});
// Assert
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal("The 'code_verifier' parameter is uncalled for in this request.", response.ErrorDescription);
}
[Fact]
public async Task ValidateTokenRequest_AuthorizationCodeCausesAnErrorWhenCodeVerifierIsMissing()
{

Loading…
Cancel
Save