|
|
|
@ -736,7 +736,7 @@ namespace OpenIddict.Server.Tests |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task HandleTokenRequest_AuthorizationCodeRevocationIsIgnoredWhenTokenRevocationIsDisabled() |
|
|
|
public async Task HandleTokenRequest_AuthorizationCodeRevocationIsIgnoredWhenTokenStorageIsDisabled() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var ticket = new AuthenticationTicket( |
|
|
|
@ -777,7 +777,7 @@ namespace OpenIddict.Server.Tests |
|
|
|
builder.Configure(options => options.AuthorizationCodeFormat = format.Object); |
|
|
|
builder.Configure(options => options.RevocationEndpointPath = PathString.Empty); |
|
|
|
|
|
|
|
builder.DisableTokenRevocation(); |
|
|
|
builder.DisableTokenStorage(); |
|
|
|
builder.DisableSlidingExpiration(); |
|
|
|
}); |
|
|
|
|
|
|
|
@ -797,7 +797,7 @@ namespace OpenIddict.Server.Tests |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task HandleTokenRequest_RefreshTokenRevocationIsIgnoredWhenTokenRevocationIsDisabled() |
|
|
|
public async Task HandleTokenRequest_RefreshTokenRevocationIsIgnoredWhenTokenStorageIsDisabled() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var ticket = new AuthenticationTicket( |
|
|
|
@ -837,7 +837,7 @@ namespace OpenIddict.Server.Tests |
|
|
|
builder.Configure(options => options.RefreshTokenFormat = format.Object); |
|
|
|
builder.Configure(options => options.RevocationEndpointPath = PathString.Empty); |
|
|
|
|
|
|
|
builder.DisableTokenRevocation(); |
|
|
|
builder.DisableTokenStorage(); |
|
|
|
builder.DisableSlidingExpiration(); |
|
|
|
}); |
|
|
|
|
|
|
|
@ -1682,6 +1682,546 @@ namespace OpenIddict.Server.Tests |
|
|
|
Mock.Get(manager).Verify(mock => mock.IsValidAsync(token, It.IsAny<CancellationToken>()), Times.Once()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task HandleTokenRequest_AuthorizationAssociatedWithCodeIsIgnoredWhenAuthorizationStorageIsDisabled() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var ticket = new AuthenticationTicket( |
|
|
|
new ClaimsPrincipal(), |
|
|
|
new AuthenticationProperties(), |
|
|
|
OpenIddictServerDefaults.AuthenticationScheme); |
|
|
|
|
|
|
|
ticket.SetPresenters("Fabrikam"); |
|
|
|
ticket.SetTokenId("3E228451-1555-46F7-A471-951EFBA23A56"); |
|
|
|
ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.AuthorizationCode); |
|
|
|
|
|
|
|
var format = new Mock<ISecureDataFormat<AuthenticationTicket>>(); |
|
|
|
|
|
|
|
format.Setup(mock => mock.Unprotect("SplxlOBeZQQYbYS6WxSbIA")) |
|
|
|
.Returns(ticket); |
|
|
|
|
|
|
|
var manager = CreateAuthorizationManager(instance => |
|
|
|
{ |
|
|
|
instance.Setup(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(new OpenIddictAuthorization()); |
|
|
|
}); |
|
|
|
|
|
|
|
var server = CreateAuthorizationServer(builder => |
|
|
|
{ |
|
|
|
builder.Services.AddSingleton(CreateApplicationManager(instance => |
|
|
|
{ |
|
|
|
var application = new OpenIddictApplication(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(application); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.Endpoints.Token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>(OpenIddictConstants.ClientTypes.Public)); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(CreateTokenManager(instance => |
|
|
|
{ |
|
|
|
var token = new OpenIddictToken(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(token); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("3E228451-1555-46F7-A471-951EFBA23A56")); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(false); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetAuthorizationIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0")); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(manager); |
|
|
|
|
|
|
|
builder.DisableAuthorizationStorage(); |
|
|
|
|
|
|
|
builder.Configure(options => options.AuthorizationCodeFormat = format.Object); |
|
|
|
}); |
|
|
|
|
|
|
|
var client = new OpenIdConnectClient(server.CreateClient()); |
|
|
|
|
|
|
|
// Act
|
|
|
|
var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest |
|
|
|
{ |
|
|
|
ClientId = "Fabrikam", |
|
|
|
Code = "SplxlOBeZQQYbYS6WxSbIA", |
|
|
|
GrantType = OpenIdConnectConstants.GrantTypes.AuthorizationCode, |
|
|
|
RedirectUri = "http://www.fabrikam.com/path" |
|
|
|
}); |
|
|
|
|
|
|
|
// Assert
|
|
|
|
Assert.NotNull(response.AccessToken); |
|
|
|
|
|
|
|
Mock.Get(manager).Verify(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>()), Times.Never()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task HandleTokenRequest_AuthorizationAssociatedWithRefreshTokenIsIgnoredWhenAuthorizationStorageIsDisabled() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var ticket = new AuthenticationTicket( |
|
|
|
new ClaimsPrincipal(), |
|
|
|
new AuthenticationProperties(), |
|
|
|
OpenIddictServerDefaults.AuthenticationScheme); |
|
|
|
|
|
|
|
ticket.SetPresenters("Fabrikam"); |
|
|
|
ticket.SetTokenId("3E228451-1555-46F7-A471-951EFBA23A56"); |
|
|
|
ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.AuthorizationCode); |
|
|
|
|
|
|
|
var format = new Mock<ISecureDataFormat<AuthenticationTicket>>(); |
|
|
|
|
|
|
|
format.Setup(mock => mock.Unprotect("SplxlOBeZQQYbYS6WxSbIA")) |
|
|
|
.Returns(ticket); |
|
|
|
|
|
|
|
var authorization = new OpenIddictAuthorization(); |
|
|
|
|
|
|
|
var manager = CreateAuthorizationManager(instance => |
|
|
|
{ |
|
|
|
instance.Setup(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(new OpenIddictAuthorization()); |
|
|
|
}); |
|
|
|
|
|
|
|
var server = CreateAuthorizationServer(builder => |
|
|
|
{ |
|
|
|
builder.Services.AddSingleton(CreateApplicationManager(instance => |
|
|
|
{ |
|
|
|
var application = new OpenIddictApplication(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(application); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.Endpoints.Token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>(OpenIddictConstants.ClientTypes.Public)); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(CreateTokenManager(instance => |
|
|
|
{ |
|
|
|
var token = new OpenIddictToken(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(token); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("3E228451-1555-46F7-A471-951EFBA23A56")); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(false); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetAuthorizationIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0")); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(manager); |
|
|
|
|
|
|
|
builder.DisableAuthorizationStorage(); |
|
|
|
|
|
|
|
builder.Configure(options => options.AuthorizationCodeFormat = format.Object); |
|
|
|
}); |
|
|
|
|
|
|
|
var client = new OpenIdConnectClient(server.CreateClient()); |
|
|
|
|
|
|
|
// Act
|
|
|
|
var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest |
|
|
|
{ |
|
|
|
ClientId = "Fabrikam", |
|
|
|
Code = "SplxlOBeZQQYbYS6WxSbIA", |
|
|
|
GrantType = OpenIdConnectConstants.GrantTypes.AuthorizationCode, |
|
|
|
RedirectUri = "http://www.fabrikam.com/path" |
|
|
|
}); |
|
|
|
|
|
|
|
// Assert
|
|
|
|
Assert.NotNull(response.AccessToken); |
|
|
|
|
|
|
|
Mock.Get(manager).Verify(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>()), Times.Never()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task HandleTokenRequest_RequestIsRejectedWhenAuthorizationAssociatedWithAuthorizationCodeCannotBeFound() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var ticket = new AuthenticationTicket( |
|
|
|
new ClaimsPrincipal(), |
|
|
|
new AuthenticationProperties(), |
|
|
|
OpenIddictServerDefaults.AuthenticationScheme); |
|
|
|
|
|
|
|
ticket.SetPresenters("Fabrikam"); |
|
|
|
ticket.SetTokenId("3E228451-1555-46F7-A471-951EFBA23A56"); |
|
|
|
ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.AuthorizationCode); |
|
|
|
|
|
|
|
var format = new Mock<ISecureDataFormat<AuthenticationTicket>>(); |
|
|
|
|
|
|
|
format.Setup(mock => mock.Unprotect("SplxlOBeZQQYbYS6WxSbIA")) |
|
|
|
.Returns(ticket); |
|
|
|
|
|
|
|
var manager = CreateAuthorizationManager(instance => |
|
|
|
{ |
|
|
|
instance.Setup(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(value: null); |
|
|
|
}); |
|
|
|
|
|
|
|
var server = CreateAuthorizationServer(builder => |
|
|
|
{ |
|
|
|
builder.Services.AddSingleton(CreateApplicationManager(instance => |
|
|
|
{ |
|
|
|
var application = new OpenIddictApplication(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(application); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.Endpoints.Token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>(OpenIddictConstants.ClientTypes.Public)); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(CreateTokenManager(instance => |
|
|
|
{ |
|
|
|
var token = new OpenIddictToken(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(token); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("3E228451-1555-46F7-A471-951EFBA23A56")); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(false); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetAuthorizationIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0")); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(manager); |
|
|
|
|
|
|
|
builder.Configure(options => options.AuthorizationCodeFormat = format.Object); |
|
|
|
}); |
|
|
|
|
|
|
|
var client = new OpenIdConnectClient(server.CreateClient()); |
|
|
|
|
|
|
|
// Act
|
|
|
|
var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest |
|
|
|
{ |
|
|
|
ClientId = "Fabrikam", |
|
|
|
Code = "SplxlOBeZQQYbYS6WxSbIA", |
|
|
|
GrantType = OpenIdConnectConstants.GrantTypes.AuthorizationCode, |
|
|
|
RedirectUri = "http://www.fabrikam.com/path" |
|
|
|
}); |
|
|
|
|
|
|
|
// Assert
|
|
|
|
Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error); |
|
|
|
Assert.Equal("The authorization associated with the authorization code is no longer valid.", response.ErrorDescription); |
|
|
|
|
|
|
|
Mock.Get(manager).Verify(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>()), Times.Once()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task HandleTokenRequest_RequestIsRejectedWhenAuthorizationAssociatedWithAuthorizationCodeIsInvalid() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var ticket = new AuthenticationTicket( |
|
|
|
new ClaimsPrincipal(), |
|
|
|
new AuthenticationProperties(), |
|
|
|
OpenIddictServerDefaults.AuthenticationScheme); |
|
|
|
|
|
|
|
ticket.SetPresenters("Fabrikam"); |
|
|
|
ticket.SetTokenId("3E228451-1555-46F7-A471-951EFBA23A56"); |
|
|
|
ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.AuthorizationCode); |
|
|
|
|
|
|
|
var format = new Mock<ISecureDataFormat<AuthenticationTicket>>(); |
|
|
|
|
|
|
|
format.Setup(mock => mock.Unprotect("SplxlOBeZQQYbYS6WxSbIA")) |
|
|
|
.Returns(ticket); |
|
|
|
|
|
|
|
var authorization = new OpenIddictAuthorization(); |
|
|
|
|
|
|
|
var manager = CreateAuthorizationManager(instance => |
|
|
|
{ |
|
|
|
instance.Setup(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(authorization); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(authorization, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(false); |
|
|
|
}); |
|
|
|
|
|
|
|
var server = CreateAuthorizationServer(builder => |
|
|
|
{ |
|
|
|
builder.Services.AddSingleton(CreateApplicationManager(instance => |
|
|
|
{ |
|
|
|
var application = new OpenIddictApplication(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(application); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.Endpoints.Token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>(OpenIddictConstants.ClientTypes.Public)); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(CreateTokenManager(instance => |
|
|
|
{ |
|
|
|
var token = new OpenIddictToken(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(token); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("3E228451-1555-46F7-A471-951EFBA23A56")); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(false); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetAuthorizationIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0")); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(manager); |
|
|
|
|
|
|
|
builder.Configure(options => options.AuthorizationCodeFormat = format.Object); |
|
|
|
}); |
|
|
|
|
|
|
|
var client = new OpenIdConnectClient(server.CreateClient()); |
|
|
|
|
|
|
|
// Act
|
|
|
|
var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest |
|
|
|
{ |
|
|
|
ClientId = "Fabrikam", |
|
|
|
Code = "SplxlOBeZQQYbYS6WxSbIA", |
|
|
|
GrantType = OpenIdConnectConstants.GrantTypes.AuthorizationCode, |
|
|
|
RedirectUri = "http://www.fabrikam.com/path" |
|
|
|
}); |
|
|
|
|
|
|
|
// Assert
|
|
|
|
Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error); |
|
|
|
Assert.Equal("The authorization associated with the authorization code is no longer valid.", response.ErrorDescription); |
|
|
|
|
|
|
|
Mock.Get(manager).Verify(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>()), Times.Once()); |
|
|
|
Mock.Get(manager).Verify(mock => mock.IsValidAsync(authorization, It.IsAny<CancellationToken>()), Times.Once()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task HandleTokenRequest_RequestIsRejectedWhenAuthorizationAssociatedWithRefreshTokenCannotBeFound() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var ticket = new AuthenticationTicket( |
|
|
|
new ClaimsPrincipal(), |
|
|
|
new AuthenticationProperties(), |
|
|
|
OpenIddictServerDefaults.AuthenticationScheme); |
|
|
|
|
|
|
|
ticket.SetTokenId("60FFF7EA-F98E-437B-937E-5073CC313103"); |
|
|
|
ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); |
|
|
|
ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, "18D15F73-BE2B-6867-DC01-B3C1E8AFDED0"); |
|
|
|
|
|
|
|
var format = new Mock<ISecureDataFormat<AuthenticationTicket>>(); |
|
|
|
|
|
|
|
format.Setup(mock => mock.Unprotect("8xLOxBtZp8")) |
|
|
|
.Returns(ticket); |
|
|
|
|
|
|
|
var manager = CreateAuthorizationManager(instance => |
|
|
|
{ |
|
|
|
instance.Setup(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(value: null); |
|
|
|
}); |
|
|
|
|
|
|
|
var server = CreateAuthorizationServer(builder => |
|
|
|
{ |
|
|
|
builder.Services.AddSingleton(CreateApplicationManager(instance => |
|
|
|
{ |
|
|
|
var application = new OpenIddictApplication(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(application); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.Endpoints.Token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>(OpenIddictConstants.ClientTypes.Public)); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(CreateTokenManager(instance => |
|
|
|
{ |
|
|
|
var token = new OpenIddictToken(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(token); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("60FFF7EA-F98E-437B-937E-5073CC313103951EFBA23A56")); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(false); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetAuthorizationIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0")); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(manager); |
|
|
|
|
|
|
|
builder.Configure(options => options.RefreshTokenFormat = format.Object); |
|
|
|
}); |
|
|
|
|
|
|
|
var client = new OpenIdConnectClient(server.CreateClient()); |
|
|
|
|
|
|
|
// Act
|
|
|
|
var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest |
|
|
|
{ |
|
|
|
GrantType = OpenIdConnectConstants.GrantTypes.RefreshToken, |
|
|
|
RefreshToken = "8xLOxBtZp8" |
|
|
|
}); |
|
|
|
|
|
|
|
// Assert
|
|
|
|
Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error); |
|
|
|
Assert.Equal("The authorization associated with the refresh token is no longer valid.", response.ErrorDescription); |
|
|
|
|
|
|
|
Mock.Get(manager).Verify(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>()), Times.Once()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task HandleTokenRequest_RequestIsRejectedWhenAuthorizationAssociatedWithRefreshTokenIsInvalid() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var ticket = new AuthenticationTicket( |
|
|
|
new ClaimsPrincipal(), |
|
|
|
new AuthenticationProperties(), |
|
|
|
OpenIddictServerDefaults.AuthenticationScheme); |
|
|
|
|
|
|
|
ticket.SetTokenId("60FFF7EA-F98E-437B-937E-5073CC313103"); |
|
|
|
ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); |
|
|
|
ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, "18D15F73-BE2B-6867-DC01-B3C1E8AFDED0"); |
|
|
|
|
|
|
|
var format = new Mock<ISecureDataFormat<AuthenticationTicket>>(); |
|
|
|
|
|
|
|
format.Setup(mock => mock.Unprotect("8xLOxBtZp8")) |
|
|
|
.Returns(ticket); |
|
|
|
|
|
|
|
var authorization = new OpenIddictAuthorization(); |
|
|
|
|
|
|
|
var manager = CreateAuthorizationManager(instance => |
|
|
|
{ |
|
|
|
instance.Setup(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(authorization); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(authorization, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(false); |
|
|
|
}); |
|
|
|
|
|
|
|
var server = CreateAuthorizationServer(builder => |
|
|
|
{ |
|
|
|
builder.Services.AddSingleton(CreateApplicationManager(instance => |
|
|
|
{ |
|
|
|
var application = new OpenIddictApplication(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(application); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.Endpoints.Token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.HasPermissionAsync(application, |
|
|
|
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>(OpenIddictConstants.ClientTypes.Public)); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(CreateTokenManager(instance => |
|
|
|
{ |
|
|
|
var token = new OpenIddictToken(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(token); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("60FFF7EA-F98E-437B-937E-5073CC313103951EFBA23A56")); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(false); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetAuthorizationIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0")); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(manager); |
|
|
|
|
|
|
|
builder.Configure(options => options.RefreshTokenFormat = format.Object); |
|
|
|
}); |
|
|
|
|
|
|
|
var client = new OpenIdConnectClient(server.CreateClient()); |
|
|
|
|
|
|
|
// Act
|
|
|
|
var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest |
|
|
|
{ |
|
|
|
GrantType = OpenIdConnectConstants.GrantTypes.RefreshToken, |
|
|
|
RefreshToken = "8xLOxBtZp8" |
|
|
|
}); |
|
|
|
|
|
|
|
// Assert
|
|
|
|
Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error); |
|
|
|
Assert.Equal("The authorization associated with the refresh token is no longer valid.", response.ErrorDescription); |
|
|
|
|
|
|
|
Mock.Get(manager).Verify(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>()), Times.Once()); |
|
|
|
Mock.Get(manager).Verify(mock => mock.IsValidAsync(authorization, It.IsAny<CancellationToken>()), Times.Once()); |
|
|
|
} |
|
|
|
|
|
|
|
[Theory] |
|
|
|
[InlineData(OpenIdConnectConstants.GrantTypes.AuthorizationCode)] |
|
|
|
[InlineData(OpenIdConnectConstants.GrantTypes.ClientCredentials)] |
|
|
|
@ -1730,6 +2270,9 @@ namespace OpenIddict.Server.Tests |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.GetAuthorizationIdAsync(token, It.IsAny<CancellationToken>())) |
|
|
|
.Returns(new ValueTask<string>("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0")); |
|
|
|
}); |
|
|
|
|
|
|
|
var server = CreateAuthorizationServer(builder => |
|
|
|
@ -1772,6 +2315,17 @@ namespace OpenIddict.Server.Tests |
|
|
|
.ReturnsAsync(true); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(CreateAuthorizationManager(instance => |
|
|
|
{ |
|
|
|
var authorization = new OpenIddictAuthorization(); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(authorization); |
|
|
|
|
|
|
|
instance.Setup(mock => mock.IsValidAsync(authorization, It.IsAny<CancellationToken>())) |
|
|
|
.ReturnsAsync(true); |
|
|
|
})); |
|
|
|
|
|
|
|
builder.AllowCustomFlow("urn:ietf:params:oauth:grant-type:custom_grant"); |
|
|
|
|
|
|
|
builder.Services.AddSingleton(manager); |
|
|
|
|