From aa6a82e85e30c61a31bda74673c1aab1cb92a3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Mon, 22 Aug 2016 19:35:20 +0200 Subject: [PATCH] Update OpenIddictProvider to allow using custom grant types --- .../OpenIddictProvider.Discovery.cs | 8 --- .../OpenIddictProvider.Exchange.cs | 67 ++----------------- src/OpenIddict.Core/OpenIddictBuilder.cs | 13 ++++ src/OpenIddict.Core/OpenIddictExtensions.cs | 10 --- 4 files changed, 20 insertions(+), 78 deletions(-) diff --git a/src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Discovery.cs b/src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Discovery.cs index 82b4417a..b86333fd 100644 --- a/src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Discovery.cs +++ b/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); } diff --git a/src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Exchange.cs b/src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Exchange.cs index 3b4c9a20..9c7dc35c 100644 --- a/src/OpenIddict.Core/Infrastructure/OpenIddictProvider.Exchange.cs +++ b/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>(); - // 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>(); - 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(); + } } } } \ No newline at end of file diff --git a/src/OpenIddict.Core/OpenIddictBuilder.cs b/src/OpenIddict.Core/OpenIddictBuilder.cs index 5be62344..f15f2541 100644 --- a/src/OpenIddict.Core/OpenIddictBuilder.cs +++ b/src/OpenIddict.Core/OpenIddictBuilder.cs @@ -456,6 +456,19 @@ namespace Microsoft.AspNetCore.Builder { OpenIdConnectConstants.GrantTypes.ClientCredentials)); } + /// + /// Enables custom grant type support. + /// + /// The grant type associated with the flow. + /// The . + 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)); + } + /// /// Enables implicit flow support. For more information /// about this specific OAuth2/OpenID Connect flow, visit diff --git a/src/OpenIddict.Core/OpenIddictExtensions.cs b/src/OpenIddict.Core/OpenIddictExtensions.cs index 00b5c240..0b24736b 100644 --- a/src/OpenIddict.Core/OpenIddictExtensions.cs +++ b/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() ||