|
|
|
@ -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() |
|
|
|
{ |
|
|
|
|