Browse Source

Port the revocation endpoint tests and disable GET support

pull/882/head
Kévin Chalet 7 years ago
parent
commit
0214951ffc
  1. 2
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Revocation.cs
  2. 2
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Revocation.cs
  3. 7
      src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
  4. 55
      test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Revocation.cs
  5. 208
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs
  6. 202
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs
  7. 685
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Introspection.cs
  8. 1128
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Revocation.cs
  9. 54
      test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Revocation.cs

2
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Revocation.cs

@ -17,7 +17,7 @@ namespace OpenIddict.Server.AspNetCore
/*
* Revocation request extraction:
*/
ExtractGetOrPostRequest<ExtractRevocationRequestContext>.Descriptor,
ExtractPostRequest<ExtractRevocationRequestContext>.Descriptor,
ExtractBasicAuthenticationCredentials<ExtractRevocationRequestContext>.Descriptor,
/*

2
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Revocation.cs

@ -17,7 +17,7 @@ namespace OpenIddict.Server.Owin
/*
* Revocation request extraction:
*/
ExtractGetOrPostRequest<ExtractRevocationRequestContext>.Descriptor,
ExtractPostRequest<ExtractRevocationRequestContext>.Descriptor,
ExtractBasicAuthenticationCredentials<ExtractRevocationRequestContext>.Descriptor,
/*

7
src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs

@ -798,7 +798,7 @@ namespace OpenIddict.Server
}
// If the received token is an access token, return an error if reference tokens are not enabled.
if (context.Principal.IsAccessToken() && !context.Options.UseReferenceAccessTokens)
if (!context.Options.UseReferenceAccessTokens && context.Principal.IsAccessToken())
{
context.Logger.LogError("The revocation request was rejected because the access token was not revocable.");
@ -1022,10 +1022,9 @@ namespace OpenIddict.Server
}
var token = await _tokenManager.FindByIdAsync(identifier);
if (token == null || await _tokenManager.HasStatusAsync(token, Statuses.Revoked))
if (token == null)
{
context.Logger.LogInformation("The token '{Identifier}' was not revoked because " +
"it was already marked as revoked.", identifier);
context.Logger.LogInformation("The token '{Identifier}' was not revoked because it couldn't be found.", identifier);
context.Reject(
error: Errors.InvalidToken,

55
test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Revocation.cs

@ -0,0 +1,55 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/openiddict/openiddict-core for more information concerning
* the license and the contributors participating to this project.
*/
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.Net.Http.Headers;
using OpenIddict.Abstractions;
using OpenIddict.Server.FunctionalTests;
using Xunit;
using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Server.OpenIddictServerEvents;
namespace OpenIddict.Server.AspNetCore.FunctionalTests
{
public partial class OpenIddictServerAspNetCoreIntegrationTests : OpenIddictServerIntegrationTests
{
[Fact]
public async Task ExtractRevocationRequest_MultipleClientCredentialsCauseAnError()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ExtractRevocationRequestContext>(builder =>
{
builder.UseInlineHandler(context =>
{
var request = context.Transaction.GetHttpRequest();
request.Headers[HeaderNames.Authorization] = "Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW";
return default;
});
builder.SetOrder(int.MinValue);
});
});
// Act
var response = await client.PostAsync("/connect/revoke", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal("Multiple client credentials cannot be specified.", response.ErrorDescription);
}
}
}

208
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs

@ -864,110 +864,6 @@ namespace OpenIddict.Server.FunctionalTests
Assert.Equal("The mandatory 'redirect_uri' parameter is missing.", response.ErrorDescription);
}
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]
[InlineData("custom_error", "custom_description", "custom_uri")]
[InlineData(null, "custom_description", null)]
[InlineData(null, "custom_description", "custom_uri")]
[InlineData(null, null, "custom_uri")]
[InlineData(null, null, null)]
public async Task ValidateAuthorizationRequest_AllowsRejectingRequest(string error, string description, string uri)
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateAuthorizationRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Reject(error, description, uri);
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "Fabrikam",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code,
Scope = Scopes.OpenId
});
// Assert
Assert.Equal(error ?? Errors.InvalidRequest, response.Error);
Assert.Equal(description, response.ErrorDescription);
Assert.Equal(uri, response.ErrorUri);
}
[Fact]
public async Task ValidateAuthorizationRequest_AllowsHandlingResponse()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateAuthorizationRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Transaction.SetProperty("custom_response", new
{
name = "Bob le Bricoleur"
});
context.HandleRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "Fabrikam",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code,
Scope = Scopes.OpenId
});
// Assert
Assert.Equal("Bob le Bricoleur", (string) response["name"]);
}
[Fact]
public async Task ValidateAuthorizationRequest_AllowsSkippingHandler()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateAuthorizationRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.SkipRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "Fabrikam",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code,
Scope = Scopes.OpenId
});
// Assert
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
[Fact]
public async Task ValidateAuthorizationRequest_MissingRedirectUriCausesAnException()
{
@ -1348,6 +1244,110 @@ namespace OpenIddict.Server.FunctionalTests
Permissions.Prefixes.Scope + Scopes.Email, It.IsAny<CancellationToken>()), Times.Once());
}
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]
[InlineData("custom_error", "custom_description", "custom_uri")]
[InlineData(null, "custom_description", null)]
[InlineData(null, "custom_description", "custom_uri")]
[InlineData(null, null, "custom_uri")]
[InlineData(null, null, null)]
public async Task ValidateAuthorizationRequest_AllowsRejectingRequest(string error, string description, string uri)
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateAuthorizationRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Reject(error, description, uri);
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "Fabrikam",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code,
Scope = Scopes.OpenId
});
// Assert
Assert.Equal(error ?? Errors.InvalidRequest, response.Error);
Assert.Equal(description, response.ErrorDescription);
Assert.Equal(uri, response.ErrorUri);
}
[Fact]
public async Task ValidateAuthorizationRequest_AllowsHandlingResponse()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateAuthorizationRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Transaction.SetProperty("custom_response", new
{
name = "Bob le Bricoleur"
});
context.HandleRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "Fabrikam",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code,
Scope = Scopes.OpenId
});
// Assert
Assert.Equal("Bob le Bricoleur", (string) response["name"]);
}
[Fact]
public async Task ValidateAuthorizationRequest_AllowsSkippingHandler()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateAuthorizationRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.SkipRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{
ClientId = "Fabrikam",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code,
Scope = Scopes.OpenId
});
// Assert
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]

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

@ -247,107 +247,6 @@ namespace OpenIddict.Server.FunctionalTests
Assert.Equal("The mandatory 'username' and/or 'password' parameters are missing.", response.ErrorDescription);
}
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]
[InlineData("custom_error", "custom_description", "custom_uri")]
[InlineData(null, "custom_description", null)]
[InlineData(null, "custom_description", "custom_uri")]
[InlineData(null, null, "custom_uri")]
[InlineData(null, null, null)]
public async Task ValidateTokenRequest_AllowsRejectingRequest(string error, string description, string uri)
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateTokenRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Reject(error, description, uri);
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/token", new OpenIddictRequest
{
GrantType = GrantTypes.Password,
Username = "johndoe",
Password = "A3ddj3w"
});
// Assert
Assert.Equal(error ?? Errors.InvalidRequest, response.Error);
Assert.Equal(description, response.ErrorDescription);
Assert.Equal(uri, response.ErrorUri);
}
[Fact]
public async Task ValidateTokenRequest_AllowsHandlingResponse()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateTokenRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Transaction.SetProperty("custom_response", new
{
name = "Bob le Bricoleur"
});
context.HandleRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/token", new OpenIddictRequest
{
GrantType = GrantTypes.Password,
Username = "johndoe",
Password = "A3ddj3w"
});
// Assert
Assert.Equal("Bob le Bricoleur", (string) response["name"]);
}
[Fact]
public async Task ValidateTokenRequest_AllowsSkippingHandler()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ExtractTokenRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.SkipRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/token", new OpenIddictRequest
{
GrantType = GrantTypes.Password,
Username = "johndoe",
Password = "A3ddj3w"
});
// Assert
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
[Fact]
public async Task ValidateTokenRequest_InvalidAuthorizationCodeCausesAnError()
{
@ -1625,6 +1524,107 @@ namespace OpenIddict.Server.FunctionalTests
Mock.Get(manager).Verify(manager => manager.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny<CancellationToken>()), Times.Once());
}
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]
[InlineData("custom_error", "custom_description", "custom_uri")]
[InlineData(null, "custom_description", null)]
[InlineData(null, "custom_description", "custom_uri")]
[InlineData(null, null, "custom_uri")]
[InlineData(null, null, null)]
public async Task ValidateTokenRequest_AllowsRejectingRequest(string error, string description, string uri)
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateTokenRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Reject(error, description, uri);
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/token", new OpenIddictRequest
{
GrantType = GrantTypes.Password,
Username = "johndoe",
Password = "A3ddj3w"
});
// Assert
Assert.Equal(error ?? Errors.InvalidRequest, response.Error);
Assert.Equal(description, response.ErrorDescription);
Assert.Equal(uri, response.ErrorUri);
}
[Fact]
public async Task ValidateTokenRequest_AllowsHandlingResponse()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ValidateTokenRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Transaction.SetProperty("custom_response", new
{
name = "Bob le Bricoleur"
});
context.HandleRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/token", new OpenIddictRequest
{
GrantType = GrantTypes.Password,
Username = "johndoe",
Password = "A3ddj3w"
});
// Assert
Assert.Equal("Bob le Bricoleur", (string) response["name"]);
}
[Fact]
public async Task ValidateTokenRequest_AllowsSkippingHandler()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ExtractTokenRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.SkipRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/token", new OpenIddictRequest
{
GrantType = GrantTypes.Password,
Username = "johndoe",
Password = "A3ddj3w"
});
// Assert
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
[Fact]
public async Task HandleTokenRequest_AuthorizationCodeRevocationIsIgnoredWhenTokenStorageIsDisabled()
{

685
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Introspection.cs

@ -147,146 +147,6 @@ namespace OpenIddict.Server.FunctionalTests
Assert.Equal("The mandatory 'token' parameter is missing.", response.ErrorDescription);
}
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]
[InlineData("custom_error", "custom_description", "custom_uri")]
[InlineData(null, "custom_description", null)]
[InlineData(null, "custom_description", "custom_uri")]
[InlineData(null, null, "custom_uri")]
[InlineData(null, null, null)]
public async Task ValidateIntrospectionRequest_AllowsRejectingRequest(string error, string description, string uri)
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<ValidateIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Reject(error, description, uri);
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal(error ?? Errors.InvalidRequest, response.Error);
Assert.Equal(description, response.ErrorDescription);
Assert.Equal(uri, response.ErrorUri);
}
[Fact]
public async Task ValidateIntrospectionRequest_AllowsHandlingResponse()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<ValidateIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Transaction.SetProperty("custom_response", new
{
name = "Bob le Bricoleur"
});
context.HandleRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal("Bob le Bricoleur", (string) response["name"]);
}
[Fact]
public async Task ValidateIntrospectionRequest_AllowsSkippingHandler()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<ValidateIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.SkipRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
[Fact]
public async Task ValidateIntrospectionRequest_InvalidTokenCausesAnError()
{
@ -589,6 +449,9 @@ namespace OpenIddict.Server.FunctionalTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.GetClientTypeAsync(application, It.IsAny<CancellationToken>()))
.ReturnsAsync(ClientTypes.Public);
mock.Setup(manager => manager.HasPermissionAsync(application,
Permissions.Endpoints.Introspection, It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
@ -655,8 +518,15 @@ namespace OpenIddict.Server.FunctionalTests
Mock.Get(manager).Verify(manager => manager.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task HandleIntrospectionRequest_BasicClaimsAreCorrectlyReturned()
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]
[InlineData("custom_error", "custom_description", "custom_uri")]
[InlineData(null, "custom_description", null)]
[InlineData(null, "custom_description", "custom_uri")]
[InlineData(null, null, "custom_uri")]
[InlineData(null, null, null)]
public async Task ValidateIntrospectionRequest_AllowsRejectingRequest(string error, string description, string uri)
{
// Arrange
var client = CreateClient(options =>
@ -670,13 +540,7 @@ namespace OpenIddict.Server.FunctionalTests
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken)
.SetAudiences("Fabrikam")
.SetPresenters("Contoso", "AdventureWorks Cycles")
.SetCreationDate(new DateTimeOffset(2016, 1, 1, 0, 0, 0, TimeSpan.Zero))
.SetExpirationDate(new DateTimeOffset(2017, 1, 1, 0, 0, 0, TimeSpan.Zero))
.SetClaim(Claims.Subject, "Bob le Magnifique")
.SetClaim(Claims.JwtId, "66B65AED-4033-4E9C-B975-A8CA7FB6FA79");
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
@ -684,33 +548,29 @@ namespace OpenIddict.Server.FunctionalTests
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.RemoveEventHandler(ValidateExpirationDate.Descriptor);
options.AddEventHandler<ValidateIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Reject(error, description, uri);
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA",
TokenTypeHint = TokenTypeHints.AccessToken
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal(11, response.GetParameters().Count());
Assert.True((bool) response[Claims.Active]);
Assert.Equal("66B65AED-4033-4E9C-B975-A8CA7FB6FA79", (string) response[Claims.JwtId]);
Assert.Equal(TokenTypes.Bearer, (string) response[Claims.TokenType]);
Assert.Equal(TokenTypeHints.AccessToken, (string) response[Claims.TokenUsage]);
Assert.Equal("http://localhost/", (string) response[Claims.Issuer]);
Assert.Equal("Bob le Magnifique", (string) response[Claims.Subject]);
Assert.Equal(1451606400, (long) response[Claims.IssuedAt]);
Assert.Equal(1451606400, (long) response[Claims.NotBefore]);
Assert.Equal(1483228800, (long) response[Claims.ExpiresAt]);
Assert.Equal("Fabrikam", (string) response[Claims.Audience]);
Assert.Equal("Contoso", (string) response[Claims.ClientId]);
Assert.Equal(error ?? Errors.InvalidRequest, response.Error);
Assert.Equal(description, response.ErrorDescription);
Assert.Equal(uri, response.ErrorUri);
}
[Fact]
public async Task HandleIntrospectionRequest_NonBasicAuthorizationCodeClaimsAreNotReturned()
public async Task ValidateIntrospectionRequest_AllowsHandlingResponse()
{
// Arrange
var client = CreateClient(options =>
@ -724,34 +584,40 @@ namespace OpenIddict.Server.FunctionalTests
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AuthorizationCode)
.SetPresenters("Fabrikam")
.SetClaim(Claims.Username, "Bob")
.SetClaim("custom_claim", "secret_value");
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<ValidateIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Transaction.SetProperty("custom_response", new
{
name = "Bob le Bricoleur"
});
context.HandleRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
Token = "2YotnFZFEjr1zCsicMWpAA",
TokenTypeHint = TokenTypeHints.AuthorizationCode
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Null(response["custom_claim"]);
Assert.Null(response[Claims.Username]);
Assert.Equal("Bob le Bricoleur", (string) response["name"]);
}
[Fact]
public async Task HandleIntrospectionRequest_NonBasicRefreshTokenClaimsAreNotReturned()
public async Task ValidateIntrospectionRequest_AllowsSkippingHandler()
{
// Arrange
var client = CreateClient(options =>
@ -765,50 +631,187 @@ namespace OpenIddict.Server.FunctionalTests
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.RefreshToken)
.SetPresenters("Fabrikam")
.SetClaim(Claims.Username, "Bob")
.SetClaim("custom_claim", "secret_value");
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<ValidateIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.SkipRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
Token = "2YotnFZFEjr1zCsicMWpAA",
TokenTypeHint = TokenTypeHints.RefreshToken
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Null(response["custom_claim"]);
Assert.Null(response[Claims.Username]);
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
[Fact]
public async Task HandleIntrospectionRequest_NonBasicAccessTokenClaimsAreReturnedToTrustedAudiences()
public async Task HandleIntrospectionRequest_BasicClaimsAreCorrectlyReturned()
{
// Arrange
var application = new OpenIddictApplication();
var manager = CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.GetClientTypeAsync(application, It.IsAny<CancellationToken>()))
.ReturnsAsync(ClientTypes.Confidential);
mock.Setup(manager => manager.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
});
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken)
.SetAudiences("Fabrikam")
.SetPresenters("Contoso", "AdventureWorks Cycles")
.SetCreationDate(new DateTimeOffset(2016, 1, 1, 0, 0, 0, TimeSpan.Zero))
.SetExpirationDate(new DateTimeOffset(2017, 1, 1, 0, 0, 0, TimeSpan.Zero))
.SetClaim(Claims.Subject, "Bob le Magnifique")
.SetClaim(Claims.JwtId, "66B65AED-4033-4E9C-B975-A8CA7FB6FA79");
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.RemoveEventHandler(ValidateExpirationDate.Descriptor);
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA",
TokenTypeHint = TokenTypeHints.AccessToken
});
// Assert
Assert.Equal(11, response.GetParameters().Count());
Assert.True((bool) response[Claims.Active]);
Assert.Equal("66B65AED-4033-4E9C-B975-A8CA7FB6FA79", (string) response[Claims.JwtId]);
Assert.Equal(TokenTypes.Bearer, (string) response[Claims.TokenType]);
Assert.Equal(TokenTypeHints.AccessToken, (string) response[Claims.TokenUsage]);
Assert.Equal("http://localhost/", (string) response[Claims.Issuer]);
Assert.Equal("Bob le Magnifique", (string) response[Claims.Subject]);
Assert.Equal(1451606400, (long) response[Claims.IssuedAt]);
Assert.Equal(1451606400, (long) response[Claims.NotBefore]);
Assert.Equal(1483228800, (long) response[Claims.ExpiresAt]);
Assert.Equal("Fabrikam", (string) response[Claims.Audience]);
Assert.Equal("Contoso", (string) response[Claims.ClientId]);
}
[Fact]
public async Task HandleIntrospectionRequest_NonBasicAuthorizationCodeClaimsAreNotReturned()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AuthorizationCode)
.SetPresenters("Fabrikam")
.SetClaim(Claims.Username, "Bob")
.SetClaim("custom_claim", "secret_value");
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
Token = "2YotnFZFEjr1zCsicMWpAA",
TokenTypeHint = TokenTypeHints.AuthorizationCode
});
// Assert
Assert.Null(response["custom_claim"]);
Assert.Null(response[Claims.Username]);
}
[Fact]
public async Task HandleIntrospectionRequest_NonBasicRefreshTokenClaimsAreNotReturned()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.RefreshToken)
.SetPresenters("Fabrikam")
.SetClaim(Claims.Username, "Bob")
.SetClaim("custom_claim", "secret_value");
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
Token = "2YotnFZFEjr1zCsicMWpAA",
TokenTypeHint = TokenTypeHints.RefreshToken
});
// Assert
Assert.Null(response["custom_claim"]);
Assert.Null(response[Claims.Username]);
}
[Fact]
public async Task HandleIntrospectionRequest_NonBasicAccessTokenClaimsAreReturnedToTrustedAudiences()
{
// Arrange
var application = new OpenIddictApplication();
var manager = CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.GetClientTypeAsync(application, It.IsAny<CancellationToken>()))
.ReturnsAsync(ClientTypes.Confidential);
mock.Setup(manager => manager.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
});
var client = CreateClient(options =>
{
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
@ -1056,146 +1059,6 @@ namespace OpenIddict.Server.FunctionalTests
Assert.Equal("value-2", ((JsonElement) response["object_claim"])[1].GetProperty("parameter_2").GetString());
}
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]
[InlineData("custom_error", "custom_description", "custom_uri")]
[InlineData(null, "custom_description", null)]
[InlineData(null, "custom_description", "custom_uri")]
[InlineData(null, null, "custom_uri")]
[InlineData(null, null, null)]
public async Task HandleIntrospectionRequest_AllowsRejectingRequest(string error, string description, string uri)
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<HandleIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Reject(error, description, uri);
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal(error ?? Errors.InvalidRequest, response.Error);
Assert.Equal(description, response.ErrorDescription);
Assert.Equal(uri, response.ErrorUri);
}
[Fact]
public async Task HandleIntrospectionRequest_AllowsHandlingResponse()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<HandleIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Transaction.SetProperty("custom_response", new
{
name = "Bob le Bricoleur"
});
context.HandleRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal("Bob le Bricoleur", (string) response["name"]);
}
[Fact]
public async Task HandleIntrospectionRequest_AllowsSkippingHandler()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<HandleIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.SkipRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
[Fact]
public async Task HandleIntrospectionRequest_RequestIsRejectedWhenReferenceTokenIsUnknown()
{
@ -1612,6 +1475,146 @@ namespace OpenIddict.Server.FunctionalTests
Mock.Get(manager).Verify(manager => manager.HasStatusAsync(token, Statuses.Valid, It.IsAny<CancellationToken>()), Times.Once());
}
[Theory]
[InlineData("custom_error", null, null)]
[InlineData("custom_error", "custom_description", null)]
[InlineData("custom_error", "custom_description", "custom_uri")]
[InlineData(null, "custom_description", null)]
[InlineData(null, "custom_description", "custom_uri")]
[InlineData(null, null, "custom_uri")]
[InlineData(null, null, null)]
public async Task HandleIntrospectionRequest_AllowsRejectingRequest(string error, string description, string uri)
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<HandleIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Reject(error, description, uri);
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal(error ?? Errors.InvalidRequest, response.Error);
Assert.Equal(description, response.ErrorDescription);
Assert.Equal(uri, response.ErrorUri);
}
[Fact]
public async Task HandleIntrospectionRequest_AllowsHandlingResponse()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<HandleIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.Transaction.SetProperty("custom_response", new
{
name = "Bob le Bricoleur"
});
context.HandleRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal("Bob le Bricoleur", (string) response["name"]);
}
[Fact]
public async Task HandleIntrospectionRequest_AllowsSkippingHandler()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ProcessAuthenticationContext>(builder =>
{
builder.UseInlineHandler(context =>
{
Assert.Equal("2YotnFZFEjr1zCsicMWpAA", context.Token);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetTokenType(TokenTypeHints.AccessToken);
return default;
});
builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500);
});
options.AddEventHandler<HandleIntrospectionRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
context.SkipRequest();
return default;
}));
});
// Act
var response = await client.PostAsync("/connect/introspect", new OpenIddictRequest
{
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
[Fact]
public async Task ApplyIntrospectionResponse_AllowsHandlingResponse()
{

1128
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Revocation.cs

File diff suppressed because it is too large

54
test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Revocation.cs

@ -0,0 +1,54 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/openiddict/openiddict-core for more information concerning
* the license and the contributors participating to this project.
*/
using System.Threading.Tasks;
using OpenIddict.Abstractions;
using OpenIddict.Server.FunctionalTests;
using Owin;
using Xunit;
using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Server.OpenIddictServerEvents;
namespace OpenIddict.Server.Owin.FunctionalTests
{
public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerIntegrationTests
{
[Fact]
public async Task ExtractRevocationRequest_MultipleClientCredentialsCauseAnError()
{
// Arrange
var client = CreateClient(options =>
{
options.EnableDegradedMode();
options.AddEventHandler<ExtractRevocationRequestContext>(builder =>
{
builder.UseInlineHandler(context =>
{
var request = context.Transaction.GetOwinRequest();
request.Headers["Authorization"] = "Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW";
return default;
});
builder.SetOrder(int.MinValue);
});
});
// Act
var response = await client.PostAsync("/connect/revoke", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
Token = "2YotnFZFEjr1zCsicMWpAA"
});
// Assert
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal("Multiple client credentials cannot be specified.", response.ErrorDescription);
}
}
}
Loading…
Cancel
Save