Browse Source

Backport the token endpoint validation logic changes to OpenIddict 1.x

pull/670/head
Kévin Chalet 8 years ago
parent
commit
a6427f193f
  1. 4
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs
  2. 36
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs
  3. 46
      test/OpenIddict.Server.Tests/Internal/OpenIddictServerProviderTests.Authentication.cs
  4. 47
      test/OpenIddict.Server.Tests/Internal/OpenIddictServerProviderTests.Exchange.cs

4
src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs

@ -382,8 +382,8 @@ namespace OpenIddict.Server
return;
}
// Reject the request if the offline_access scope was request and if the
// application is not allowed to use the authorization code/implicit flows.
// Reject the request if the offline_access scope was request and if
// the application is not allowed to use the refresh token grant type.
if (context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess) &&
!await applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.RefreshToken))
{

36
src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs

@ -188,18 +188,36 @@ namespace OpenIddict.Server
return;
}
// Reject the request if the application is not allowed to use the specified grant type.
if (!options.IgnoreGrantTypePermissions && !await applicationManager.HasPermissionAsync(application,
OpenIddictConstants.Permissions.Prefixes.GrantType + context.Request.GrantType))
if (!options.IgnoreGrantTypePermissions)
{
logger.LogError("The token request was rejected because the application '{ClientId}' was not allowed to " +
"use the specified grant type: {GrantType}.", context.ClientId, context.Request.GrantType);
// Reject the request if the application is not allowed to use the specified grant type.
if (!await applicationManager.HasPermissionAsync(application,
OpenIddictConstants.Permissions.Prefixes.GrantType + context.Request.GrantType))
{
logger.LogError("The token request was rejected because the application '{ClientId}' was not allowed to " +
"use the specified grant type: {GrantType}.", context.ClientId, context.Request.GrantType);
context.Reject(
error: OpenIdConnectConstants.Errors.UnauthorizedClient,
description: "This client application is not allowed to use the specified grant type.");
context.Reject(
error: OpenIdConnectConstants.Errors.UnauthorizedClient,
description: "This client application is not allowed to use the specified grant type.");
return;
return;
}
// Reject the request if the offline_access scope was request and if
// the application is not allowed to use the refresh token grant type.
if (context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess) &&
!await applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.RefreshToken))
{
logger.LogError("The token request was rejected because the application '{ClientId}' " +
"was not allowed to request the 'offline_access' scope.", context.ClientId);
context.Reject(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The client application is not allowed to use the 'offline_access' scope.");
return;
}
}
if (await applicationManager.IsPublicAsync(application))

46
test/OpenIddict.Server.Tests/Internal/OpenIddictServerProviderTests.Authentication.cs

@ -656,6 +656,52 @@ namespace OpenIddict.Server.Tests
Mock.Get(manager).Verify(mock => mock.HasPermissionAsync(application, permissions[0], It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task ValidateAuthorizationRequest_RequestWithOfflineAccessScopeIsRejectedWhenRefreshTokenPermissionIsNotGranted()
{
// Arrange
var application = new OpenIddictApplication();
var manager = CreateApplicationManager(instance =>
{
instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
instance.Setup(mock => mock.HasPermissionAsync(application,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
instance.Setup(mock => mock.HasPermissionAsync(application,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
});
var server = CreateAuthorizationServer(builder =>
{
builder.Services.AddSingleton(manager);
builder.Configure(options => options.IgnoreGrantTypePermissions = false);
});
var client = new OpenIdConnectClient(server.CreateClient());
// Act
var response = await client.PostAsync(AuthorizationEndpoint, new OpenIdConnectRequest
{
ClientId = "Fabrikam",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = OpenIdConnectConstants.ResponseTypes.Code,
Scope = OpenIdConnectConstants.Scopes.OfflineAccess
});
// Assert
Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
Assert.Equal("The client application is not allowed to use the 'offline_access' scope.", response.ErrorDescription);
Mock.Get(manager).Verify(mock => mock.HasPermissionAsync(application,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task ValidateAuthorizationRequest_RequestIsRejectedWhenRedirectUriIsInvalid()
{

47
test/OpenIddict.Server.Tests/Internal/OpenIddictServerProviderTests.Exchange.cs

@ -389,6 +389,53 @@ namespace OpenIddict.Server.Tests
OpenIddictConstants.Permissions.GrantTypes.Password, It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task ValidateTokenRequest_RequestWithOfflineAccessScopeIsRejectedWhenRefreshTokenPermissionIsNotGranted()
{
// Arrange
var application = new OpenIddictApplication();
var manager = CreateApplicationManager(instance =>
{
instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
instance.Setup(mock => mock.HasPermissionAsync(application,
OpenIddictConstants.Permissions.GrantTypes.Password, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
instance.Setup(mock => mock.HasPermissionAsync(application,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
});
var server = CreateAuthorizationServer(builder =>
{
builder.Services.AddSingleton(manager);
builder.Configure(options => options.IgnoreGrantTypePermissions = false);
});
var client = new OpenIdConnectClient(server.CreateClient());
// Act
var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest
{
ClientId = "Fabrikam",
GrantType = OpenIdConnectConstants.GrantTypes.Password,
Username = "johndoe",
Password = "A3ddj3w",
Scope = OpenIdConnectConstants.Scopes.OfflineAccess
});
// Assert
Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
Assert.Equal("The client application is not allowed to use the 'offline_access' scope.", response.ErrorDescription);
Mock.Get(manager).Verify(mock => mock.HasPermissionAsync(application,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task ValidateTokenRequest_ClientCredentialsRequestFromPublicClientIsRejected()
{

Loading…
Cancel
Save