Browse Source

Update OpenIddictProvider to allow using custom grant types

pull/205/head
Kévin Chalet 10 years ago
parent
commit
aa6a82e85e
  1. 8
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Discovery.cs
  2. 67
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Exchange.cs
  3. 13
      src/OpenIddict.Core/OpenIddictBuilder.cs
  4. 10
      src/OpenIddict.Core/OpenIddictExtensions.cs

8
src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Discovery.cs

@ -4,7 +4,6 @@
* the license and the contributors participating to this project.
*/
using System.Diagnostics;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Server;
@ -30,13 +29,6 @@ namespace OpenIddict.Infrastructure {
// Copy the supported grant types list to the discovery document.
foreach (var type in services.Options.GrantTypes) {
Debug.Assert(type == OpenIdConnectConstants.GrantTypes.AuthorizationCode ||
type == OpenIdConnectConstants.GrantTypes.ClientCredentials ||
type == OpenIdConnectConstants.GrantTypes.Implicit ||
type == OpenIdConnectConstants.GrantTypes.Password ||
type == OpenIdConnectConstants.GrantTypes.RefreshToken,
"Unsupported or non-standard OAuth2/OIDC grant types should not be exposed.");
context.GrantTypes.Add(type);
}

67
src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Exchange.cs

@ -23,66 +23,14 @@ namespace OpenIddict.Infrastructure {
public override async Task ValidateTokenRequest([NotNull] ValidateTokenRequestContext context) {
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>();
// Note: the OpenID Connect server middleware supports authorization code, refresh token, client credentials,
// resource owner password credentials and custom grants but OpenIddict uses a stricter policy rejecting custom grants.
if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType() &&
!context.Request.IsPasswordGrantType() && !context.Request.IsClientCredentialsGrantType()) {
// Reject token requests that don't specify a supported grant type.
if (!services.Options.GrantTypes.Contains(context.Request.GrantType)) {
services.Logger.LogError("The token request was rejected because the '{Grant}' " +
"grant is not supported.", context.Request.GrantType);
context.Reject(
error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
description: "Only authorization code, refresh token, client credentials " +
"and password grants are accepted by this authorization server.");
return;
}
// Reject token requests using grant_type=authorization_code
// if the authorization code flow support is not enabled.
if (context.Request.IsAuthorizationCodeGrantType() && !services.Options.IsAuthorizationCodeFlowEnabled()) {
services.Logger.LogError("The token request was rejected because the authorization code flow was not enabled.");
context.Reject(
error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
description: "The specified grant_type parameter is not allowed.");
return;
}
// Reject token requests using grant_type=client_credentials
// if the client credentials flow support is not enabled.
else if (context.Request.IsClientCredentialsGrantType() && !services.Options.IsClientCredentialsFlowEnabled()) {
services.Logger.LogError("The token request was rejected because the client credentials flow was not enabled.");
context.Reject(
error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
description: "The specified grant_type parameter is not allowed.");
return;
}
// Reject token requests using grant_type=password if the
// resource owner password credentials flow support is not enabled.
else if (context.Request.IsPasswordGrantType() && !services.Options.IsPasswordFlowEnabled()) {
services.Logger.LogError("The token request was rejected because the resource " +
"owner password credentials flow was not enabled.");
context.Reject(
error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
description: "The specified grant_type parameter is not allowed.");
return;
}
// Reject token requests using grant_type=refresh_token
// if the refresh token flow support is not enabled.
if (context.Request.IsRefreshTokenGrantType() && !services.Options.IsRefreshTokenFlowEnabled()) {
services.Logger.LogError("The token request was rejected because the refresh token flow was not enabled.");
context.Reject(
error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
description: "The specified grant_type parameter is not allowed.");
description: "The specified grant_type is not supported by this authorization server.");
return;
}
@ -222,11 +170,6 @@ namespace OpenIddict.Infrastructure {
public override async Task HandleTokenRequest([NotNull] HandleTokenRequestContext context) {
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>();
Debug.Assert(context.Request.IsAuthorizationCodeGrantType() ||
context.Request.IsClientCredentialsGrantType() ||
context.Request.IsPasswordGrantType() ||
context.Request.IsRefreshTokenGrantType(), "The grant_type parameter should be a supported value.");
// Note: the OpenID Connect server middleware automatically reuses the authentication ticket
// stored in the authorization code to create a new identity. To ensure the user was not removed
// after the authorization code was issued, a new check is made before validating the request.
@ -412,6 +355,10 @@ namespace OpenIddict.Infrastructure {
context.SkipToNextMiddleware();
}
else {
context.SkipToNextMiddleware();
}
}
}
}

13
src/OpenIddict.Core/OpenIddictBuilder.cs

@ -456,6 +456,19 @@ namespace Microsoft.AspNetCore.Builder {
OpenIdConnectConstants.GrantTypes.ClientCredentials));
}
/// <summary>
/// Enables custom grant type support.
/// </summary>
/// <param name="type">The grant type associated with the flow.</param>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public virtual OpenIddictBuilder AllowCustomFlow([NotNull] string type) {
if (string.IsNullOrEmpty(type)) {
throw new ArgumentException("The grant type cannot be null or empty.", nameof(type));
}
return Configure(options => options.GrantTypes.Add(type));
}
/// <summary>
/// Enables implicit flow support. For more information
/// about this specific OAuth2/OpenID Connect flow, visit

10
src/OpenIddict.Core/OpenIddictExtensions.cs

@ -104,16 +104,6 @@ namespace Microsoft.AspNetCore.Builder {
throw new InvalidOperationException("At least one OAuth2/OpenID Connect flow must be enabled.");
}
// Ensure only supported grant types are listed to prevent
// unknown flows from being exposed in the discovery document.
if (options.GrantTypes.Any(type => type != OpenIdConnectConstants.GrantTypes.AuthorizationCode &&
type != OpenIdConnectConstants.GrantTypes.ClientCredentials &&
type != OpenIdConnectConstants.GrantTypes.Implicit &&
type != OpenIdConnectConstants.GrantTypes.Password &&
type != OpenIdConnectConstants.GrantTypes.RefreshToken)) {
throw new InvalidOperationException("Only supported flows can be enabled.");
}
// Ensure the authorization endpoint has been enabled when
// the authorization code or implicit grants are supported.
if (!options.AuthorizationEndpointPath.HasValue && (options.IsAuthorizationCodeFlowEnabled() ||

Loading…
Cancel
Save