diff --git a/samples/Mvc.Server/Startup.cs b/samples/Mvc.Server/Startup.cs
index d21963b5..9daf7098 100644
--- a/samples/Mvc.Server/Startup.cs
+++ b/samples/Mvc.Server/Startup.cs
@@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
@@ -135,6 +136,16 @@ namespace Mvc.Server
app.UseStatusCodePagesWithReExecute("/error");
+ // Note: ASP.NET Core is impacted by a bug that prevents the status code pages
+ // from working correctly with endpoint routing. For more information, visit
+ // https://github.com/aspnet/AspNetCore/issues/13715#issuecomment-528929683.
+ app.Use((context, next) =>
+ {
+ context.SetEndpoint(null);
+
+ return next();
+ });
+
app.UseRouting();
app.UseAuthentication();
diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
index 321bf763..6d1bcddb 100644
--- a/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
+++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
@@ -79,6 +79,25 @@ namespace OpenIddict.Abstractions
return ImmutableHashSet.CreateRange(StringComparer.Ordinal, GetValues(request.AcrValues, Separators.Space));
}
+ ///
+ /// Extracts the response types from an .
+ ///
+ /// The instance.
+ public static ImmutableHashSet GetResponseTypes([NotNull] this OpenIddictRequest request)
+ {
+ if (request == null)
+ {
+ throw new ArgumentNullException(nameof(request));
+ }
+
+ if (string.IsNullOrEmpty(request.ResponseType))
+ {
+ return ImmutableHashSet.Create(StringComparer.Ordinal);
+ }
+
+ return ImmutableHashSet.CreateRange(StringComparer.Ordinal, GetValues(request.ResponseType, Separators.Space));
+ }
+
///
/// Extracts the scopes from an .
///
diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
index 7be2b39f..d125005a 100644
--- a/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
+++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
@@ -231,8 +231,7 @@ namespace OpenIddict.Abstractions
/// Gets all the parameters associated with this instance.
///
/// The parameters associated with this instance.
- public ImmutableDictionary GetParameters()
- => Parameters.ToImmutableDictionary(StringComparer.Ordinal);
+ public IReadOnlyDictionary GetParameters() => Parameters;
///
/// Determines whether the current message contains the specified parameter.
diff --git a/src/OpenIddict.Server/OpenIddictServerConfiguration.cs b/src/OpenIddict.Server/OpenIddictServerConfiguration.cs
index 8f6834da..d83e339a 100644
--- a/src/OpenIddict.Server/OpenIddictServerConfiguration.cs
+++ b/src/OpenIddict.Server/OpenIddictServerConfiguration.cs
@@ -172,6 +172,36 @@ namespace OpenIddict.Server
options.Scopes.Add(Scopes.OfflineAccess);
}
+ if (options.GrantTypes.Contains(GrantTypes.AuthorizationCode))
+ {
+ options.ResponseTypes.Add(ResponseTypes.Code);
+ }
+
+ if (options.GrantTypes.Contains(GrantTypes.Implicit))
+ {
+ options.ResponseTypes.Add(ResponseTypes.IdToken);
+ options.ResponseTypes.Add(ResponseTypes.IdToken + ' ' + ResponseTypes.Token);
+ options.ResponseTypes.Add(ResponseTypes.Token);
+ }
+
+ if (options.GrantTypes.Contains(GrantTypes.AuthorizationCode) && options.GrantTypes.Contains(GrantTypes.Implicit))
+ {
+ options.ResponseTypes.Add(ResponseTypes.Code + ' ' + ResponseTypes.IdToken);
+ options.ResponseTypes.Add(ResponseTypes.Code + ' ' + ResponseTypes.IdToken + ' ' + ResponseTypes.Token);
+ options.ResponseTypes.Add(ResponseTypes.Code + ' ' + ResponseTypes.Token);
+ }
+
+ if (options.ResponseTypes.Count != 0)
+ {
+ options.ResponseModes.Add(ResponseModes.FormPost);
+ options.ResponseModes.Add(ResponseModes.Fragment);
+
+ if (options.ResponseTypes.Contains(ResponseTypes.Code))
+ {
+ options.ResponseModes.Add(ResponseModes.Query);
+ }
+ }
+
foreach (var key in options.EncryptionCredentials
.Select(credentials => credentials.Key)
.Concat(options.SigningCredentials.Select(credentials => credentials.Key)))
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
index c8b6d314..3f8ffe0a 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Immutable;
+using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
@@ -44,6 +45,7 @@ namespace OpenIddict.Server
ValidateRedirectUriParameter.Descriptor,
ValidateResponseTypeParameter.Descriptor,
ValidateResponseModeParameter.Descriptor,
+ ValidateScopeParameter.Descriptor,
ValidateNonceParameter.Descriptor,
ValidatePromptParameter.Descriptor,
ValidateCodeChallengeParameters.Descriptor,
@@ -363,6 +365,12 @@ namespace OpenIddict.Server
context.SkipRequest();
return;
}
+
+ throw new InvalidOperationException(new StringBuilder()
+ .Append("The authorization response was not correctly applied. To apply authorization response, ")
+ .Append("create a class implementing 'IOpenIddictServerHandler' ")
+ .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
+ .ToString());
}
}
@@ -632,32 +640,10 @@ namespace OpenIddict.Server
return default;
}
- // Reject requests containing the id_token response_type if no openid scope has been received.
- if (context.Request.HasResponseType(ResponseTypes.IdToken) && !context.Request.HasScope(Scopes.OpenId))
- {
- context.Logger.LogError("The authorization request was rejected because the 'openid' scope was missing.");
-
- context.Reject(
- error: Errors.InvalidRequest,
- description: "The mandatory 'openid' scope is missing.");
-
- return default;
- }
-
- // Reject requests containing the code response_type if the token endpoint has been disabled.
- if (context.Request.HasResponseType(ResponseTypes.Code) && context.Options.TokenEndpointUris.Count == 0)
- {
- context.Logger.LogError("The authorization request was rejected because the authorization code flow was disabled.");
-
- context.Reject(
- error: Errors.UnsupportedResponseType,
- description: "The specified 'response_type' is not supported by this server.");
-
- return default;
- }
-
// Reject requests that specify an unsupported response_type.
- if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() && !context.Request.IsImplicitFlow())
+ var types = context.Request.GetResponseTypes();
+ if (!context.Options.ResponseTypes.Any(type =>
+ types.SetEquals(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))))
{
context.Logger.LogError("The authorization request was rejected because the '{ResponseType}' " +
"response type is not supported.", context.Request.ResponseType);
@@ -669,71 +655,110 @@ namespace OpenIddict.Server
return default;
}
- // Reject code flow authorization requests if the authorization code flow is not enabled.
- if (context.Request.IsAuthorizationCodeFlow() && !context.Options.GrantTypes.Contains(GrantTypes.AuthorizationCode))
- {
- context.Logger.LogError("The authorization request was rejected because " +
- "the authorization code flow was not enabled.");
+ return default;
+ }
+ }
- context.Reject(
- error: Errors.UnsupportedResponseType,
- description: "The specified 'response_type' parameter is not allowed.");
+ ///
+ /// Contains the logic responsible of rejecting authorization requests that specify an invalid response_mode parameter.
+ ///
+ public class ValidateResponseModeParameter : IOpenIddictServerHandler
+ {
+ ///
+ /// Gets the default descriptor definition assigned to this handler.
+ ///
+ public static OpenIddictServerHandlerDescriptor Descriptor { get; }
+ = OpenIddictServerHandlerDescriptor.CreateBuilder()
+ .UseSingletonHandler()
+ .SetOrder(ValidateResponseTypeParameter.Descriptor.Order + 1_000)
+ .Build();
- return default;
+ ///
+ /// Processes the event.
+ ///
+ /// The context associated with the event to process.
+ ///
+ /// A that can be used to monitor the asynchronous operation.
+ ///
+ public ValueTask HandleAsync([NotNull] ValidateAuthorizationRequestContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
}
- // Reject implicit flow authorization requests if the implicit flow is not enabled.
- if (context.Request.IsImplicitFlow() && !context.Options.GrantTypes.Contains(GrantTypes.Implicit))
+ // response_mode=query (explicit or not) and a response_type containing id_token
+ // or token are not considered as a safe combination and MUST be rejected.
+ // See http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#Security.
+ if (context.Request.IsQueryResponseMode() && (context.Request.HasResponseType(ResponseTypes.IdToken) ||
+ context.Request.HasResponseType(ResponseTypes.Token)))
{
- context.Logger.LogError("The authorization request was rejected because the implicit flow was not enabled.");
+ context.Logger.LogError("The authorization request was rejected because the 'response_type'/'response_mode' " +
+ "combination was invalid: {ResponseType} ; {ResponseMode}.",
+ context.Request.ResponseType, context.Request.ResponseMode);
context.Reject(
- error: Errors.UnsupportedResponseType,
- description: "The specified 'response_type' parameter is not allowed.");
+ error: Errors.InvalidRequest,
+ description: "The specified 'response_type'/'response_mode' combination is invalid.");
return default;
}
- // Reject hybrid flow authorization requests if the authorization code or the implicit flows are not enabled.
- if (context.Request.IsHybridFlow() && (!context.Options.GrantTypes.Contains(GrantTypes.AuthorizationCode) ||
- !context.Options.GrantTypes.Contains(GrantTypes.Implicit)))
+ // Reject requests that specify an unsupported response_mode or don't specify a different response_mode
+ // if the default response_mode inferred from the response_type was explicitly disabled in the options.
+ if (!ValidateResponseMode(context.Request, context.Options))
{
- context.Logger.LogError("The authorization request was rejected because the " +
- "authorization code flow or the implicit flow was not enabled.");
+ context.Logger.LogError("The authorization request was rejected because the '{ResponseMode}' " +
+ "response mode is not supported.", context.Request.ResponseMode);
context.Reject(
- error: Errors.UnsupportedResponseType,
- description: "The specified 'response_type' parameter is not allowed.");
+ error: Errors.InvalidRequest,
+ description: "The specified 'response_mode' parameter is not supported.");
return default;
}
- // Reject authorization requests that specify scope=offline_access if the refresh token flow is not enabled.
- if (context.Request.HasScope(Scopes.OfflineAccess) && !context.Options.GrantTypes.Contains(GrantTypes.RefreshToken))
+ return default;
+
+ static bool ValidateResponseMode(OpenIddictRequest request, OpenIddictServerOptions options)
{
- context.Reject(
- error: Errors.InvalidRequest,
- description: "The 'offline_access' scope is not allowed.");
+ // Note: both the fragment and query response modes are used as default response modes
+ // when using the implicit/hybrid and code flows if no explicit value was set.
+ // To ensure requests are rejected if the default response mode was manually disabled,
+ // the fragment and query response modes are checked first using the appropriate extensions.
- return default;
- }
+ if (request.IsFragmentResponseMode())
+ {
+ return options.ResponseModes.Contains(ResponseModes.Fragment);
+ }
- return default;
+ if (request.IsQueryResponseMode())
+ {
+ return options.ResponseModes.Contains(ResponseModes.Query);
+ }
+
+ if (string.IsNullOrEmpty(request.ResponseMode))
+ {
+ return true;
+ }
+
+ return options.ResponseModes.Contains(request.ResponseMode);
+ }
}
}
///
- /// Contains the logic responsible of rejecting authorization requests that specify an invalid response_mode parameter.
+ /// Contains the logic responsible of rejecting authorization requests that don't specify a valid scope parameter.
///
- public class ValidateResponseModeParameter : IOpenIddictServerHandler
+ public class ValidateScopeParameter : IOpenIddictServerHandler
{
///
/// Gets the default descriptor definition assigned to this handler.
///
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder()
- .UseSingletonHandler()
- .SetOrder(ValidateResponseTypeParameter.Descriptor.Order + 1_000)
+ .UseSingletonHandler()
+ .SetOrder(ValidateResponseModeParameter.Descriptor.Order + 1_000)
.Build();
///
@@ -750,34 +775,24 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
- // response_mode=query (explicit or not) and a response_type containing id_token
- // or token are not considered as a safe combination and MUST be rejected.
- // See http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#Security.
- if (context.Request.IsQueryResponseMode() && (context.Request.HasResponseType(ResponseTypes.IdToken) ||
- context.Request.HasResponseType(ResponseTypes.Token)))
+ // Reject authorization requests containing the id_token response_type if no openid scope has been received.
+ if (context.Request.HasResponseType(ResponseTypes.IdToken) && !context.Request.HasScope(Scopes.OpenId))
{
- context.Logger.LogError("The authorization request was rejected because the 'response_type'/'response_mode' " +
- "combination was invalid: {ResponseType} ; {ResponseMode}.",
- context.Request.ResponseType, context.Request.ResponseMode);
+ context.Logger.LogError("The authorization request was rejected because the 'openid' scope was missing.");
context.Reject(
error: Errors.InvalidRequest,
- description: "The specified 'response_type'/'response_mode' combination is invalid.");
+ description: "The mandatory 'openid' scope is missing.");
return default;
}
- // Reject requests that specify an unsupported response_mode.
- if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
- !context.Request.IsFragmentResponseMode() &&
- !context.Request.IsQueryResponseMode())
+ // Reject authorization requests that specify scope=offline_access if the refresh token flow is not enabled.
+ if (context.Request.HasScope(Scopes.OfflineAccess) && !context.Options.GrantTypes.Contains(GrantTypes.RefreshToken))
{
- context.Logger.LogError("The authorization request was rejected because the '{ResponseMode}' " +
- "response mode is not supported.", context.Request.ResponseMode);
-
context.Reject(
error: Errors.InvalidRequest,
- description: "The specified 'response_mode' parameter is not supported.");
+ description: "The 'offline_access' scope is not allowed.");
return default;
}
@@ -797,7 +812,7 @@ namespace OpenIddict.Server
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder()
.UseSingletonHandler()
- .SetOrder(ValidateResponseModeParameter.Descriptor.Order + 1_000)
+ .SetOrder(ValidateScopeParameter.Descriptor.Order + 1_000)
.Build();
///
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
index 45e7a812..eac975c2 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
@@ -353,6 +353,12 @@ namespace OpenIddict.Server
context.SkipRequest();
return;
}
+
+ throw new InvalidOperationException(new StringBuilder()
+ .Append("The configuration response was not correctly applied. To apply configuration response, ")
+ .Append("create a class implementing 'IOpenIddictServerHandler' ")
+ .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
+ .ToString());
}
}
@@ -499,11 +505,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
- // Only populate grant_type_supported if the authorization or token endpoints are enabled.
- if (context.AuthorizationEndpoint != null || context.TokenEndpoint != null)
- {
- context.GrantTypes.UnionWith(context.Options.GrantTypes);
- }
+ context.GrantTypes.UnionWith(context.Options.GrantTypes);
return default;
}
@@ -537,13 +539,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
- // Only populate response_modes_supported if the authorization endpoint is enabled.
- if (context.AuthorizationEndpoint != null)
- {
- context.ResponseModes.Add(ResponseModes.FormPost);
- context.ResponseModes.Add(ResponseModes.Fragment);
- context.ResponseModes.Add(ResponseModes.Query);
- }
+ context.ResponseModes.UnionWith(context.Options.ResponseModes);
return default;
}
@@ -577,25 +573,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
- if (context.GrantTypes.Contains(GrantTypes.AuthorizationCode))
- {
- context.ResponseTypes.Add(ResponseTypes.Code);
- }
-
- if (context.GrantTypes.Contains(GrantTypes.AuthorizationCode) &&
- context.GrantTypes.Contains(GrantTypes.Implicit))
- {
- context.ResponseTypes.Add(ResponseTypes.Code + ' ' + ResponseTypes.IdToken);
- context.ResponseTypes.Add(ResponseTypes.Code + ' ' + ResponseTypes.IdToken + ' ' + ResponseTypes.Token);
- context.ResponseTypes.Add(ResponseTypes.Code + ' ' + ResponseTypes.Token);
- }
-
- if (context.GrantTypes.Contains(GrantTypes.Implicit))
- {
- context.ResponseTypes.Add(ResponseTypes.IdToken);
- context.ResponseTypes.Add(ResponseTypes.IdToken + ' ' + ResponseTypes.Token);
- context.ResponseTypes.Add(ResponseTypes.Token);
- }
+ context.ResponseTypes.UnionWith(context.Options.ResponseTypes);
return default;
}
@@ -1224,6 +1202,12 @@ namespace OpenIddict.Server
context.SkipRequest();
return;
}
+
+ throw new InvalidOperationException(new StringBuilder()
+ .Append("The cryptography response was not correctly applied. To apply cryptography response, ")
+ .Append("create a class implementing 'IOpenIddictServerHandler' ")
+ .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
+ .ToString());
}
}
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
index 8e6a034f..300e9006 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
@@ -355,6 +355,12 @@ namespace OpenIddict.Server
context.SkipRequest();
return;
}
+
+ throw new InvalidOperationException(new StringBuilder()
+ .Append("The token response was not correctly applied. To apply token response, ")
+ .Append("create a class implementing 'IOpenIddictServerHandler' ")
+ .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
+ .ToString());
}
}
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
index 53fb8bb2..12f738e7 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
@@ -369,6 +369,12 @@ namespace OpenIddict.Server
context.SkipRequest();
return;
}
+
+ throw new InvalidOperationException(new StringBuilder()
+ .Append("The introspection response was not correctly applied. To apply introspection response, ")
+ .Append("create a class implementing 'IOpenIddictServerHandler' ")
+ .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
+ .ToString());
}
}
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
index 6989c537..6424800d 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
@@ -317,6 +317,12 @@ namespace OpenIddict.Server
context.SkipRequest();
return;
}
+
+ throw new InvalidOperationException(new StringBuilder()
+ .Append("The revocation response was not correctly applied. To apply revocation response, ")
+ .Append("create a class implementing 'IOpenIddictServerHandler' ")
+ .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
+ .ToString());
}
}
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
index a4ea3221..fb7479e3 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
@@ -341,6 +341,12 @@ namespace OpenIddict.Server
context.SkipRequest();
return;
}
+
+ throw new InvalidOperationException(new StringBuilder()
+ .Append("The revocation response was not correctly applied. To apply revocation response, ")
+ .Append("create a class implementing 'IOpenIddictServerHandler' ")
+ .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
+ .ToString());
}
}
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs
index 2e0f409e..2a4f51d1 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs
@@ -345,6 +345,12 @@ namespace OpenIddict.Server
context.SkipRequest();
return;
}
+
+ throw new InvalidOperationException(new StringBuilder()
+ .Append("The userinfo response was not correctly applied. To apply userinfo response, ")
+ .Append("create a class implementing 'IOpenIddictServerHandler' ")
+ .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
+ .ToString());
}
}
diff --git a/src/OpenIddict.Server/OpenIddictServerOptions.cs b/src/OpenIddict.Server/OpenIddictServerOptions.cs
index 97694df6..3a8c5709 100644
--- a/src/OpenIddict.Server/OpenIddictServerOptions.cs
+++ b/src/OpenIddict.Server/OpenIddictServerOptions.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Abstractions;
@@ -123,6 +124,7 @@ namespace OpenIddict.Server
/// This option MUST be enabled with extreme caution and custom handlers MUST be registered to
/// properly validate OpenID Connect requests.
///
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
public bool EnableDegradedMode { get; set; }
///
@@ -189,6 +191,22 @@ namespace OpenIddict.Server
///
public ISet GrantTypes { get; } = new HashSet(StringComparer.Ordinal);
+ ///
+ /// Gets the OAuth 2.0/OpenID Connect response types enabled for this application.
+ /// Response types are automatically inferred from the supported standard grant types,
+ /// but additional values can be added for advanced scenarios (e.g custom type support).
+ ///
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public ISet ResponseTypes { get; } = new HashSet(StringComparer.Ordinal);
+
+ ///
+ /// Gets the OAuth 2.0/OpenID Connect response modes enabled for this application.
+ /// Response modes are automatically inferred from the supported standard grant types,
+ /// but additional values can be added for advanced scenarios (e.g custom mode support).
+ ///
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public ISet ResponseModes { get; } = new HashSet(StringComparer.Ordinal);
+
///
/// Gets or sets a boolean indicating whether endpoint permissions should be ignored.
/// Setting this property to true is NOT recommended, unless all