Browse Source

Promote the Issuer address to a global transaction property

pull/796/head
Kévin Chalet 7 years ago
committed by GitHub
parent
commit
fef92dfb27
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 39
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs
  2. 70
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Discovery.cs
  3. 50
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Exchange.cs
  4. 69
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Introspection.cs
  5. 160
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Serialization.cs
  6. 39
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs
  7. 111
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Userinfo.cs
  8. 99
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs
  9. 38
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs
  10. 70
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Discovery.cs
  11. 41
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Exchange.cs
  12. 69
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Introspection.cs
  13. 160
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Serialization.cs
  14. 39
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs
  15. 114
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Userinfo.cs
  16. 92
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs
  17. 5
      src/OpenIddict.Server/OpenIddictServerEvents.Discovery.cs
  18. 6
      src/OpenIddict.Server/OpenIddictServerEvents.Introspection.cs
  19. 5
      src/OpenIddict.Server/OpenIddictServerEvents.Serialization.cs
  20. 5
      src/OpenIddict.Server/OpenIddictServerEvents.Userinfo.cs
  21. 9
      src/OpenIddict.Server/OpenIddictServerEvents.cs
  22. 40
      src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
  23. 3
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  24. 12
      src/OpenIddict.Server/OpenIddictServerHandlers.Serialization.cs
  25. 42
      src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs
  26. 1
      src/OpenIddict.Server/OpenIddictServerProvider.cs
  27. 5
      src/OpenIddict.Server/OpenIddictServerTransaction.cs

39
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs

@ -46,7 +46,7 @@ namespace OpenIddict.Server.AspNetCore
/*
* Authorization request handling:
*/
EnablePassthroughMode.Descriptor,
EnablePassthroughMode<HandleAuthorizationRequestContext, RequireAuthorizationEndpointPassthroughEnabled>.Descriptor,
/*
* Authorization response processing:
@ -239,43 +239,6 @@ namespace OpenIddict.Server.AspNetCore
}
}
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class EnablePassthroughMode : IOpenIddictServerHandler<HandleAuthorizationRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleAuthorizationRequestContext>()
.AddFilter<RequireHttpRequest>()
.AddFilter<RequireAuthorizationEndpointPassthroughEnabled>()
.UseSingletonHandler<EnablePassthroughMode>()
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleAuthorizationRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
}
}
/// <summary>
/// Contains the logic responsible of removing cached authorization requests from the distributed cache.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.

70
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Discovery.cs

@ -4,12 +4,7 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore;
using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters;
using static OpenIddict.Server.OpenIddictServerEvents;
namespace OpenIddict.Server.AspNetCore
@ -24,11 +19,6 @@ namespace OpenIddict.Server.AspNetCore
*/
ExtractGetRequest<ExtractConfigurationRequestContext>.Descriptor,
/*
* Configuration request handling:
*/
InferIssuerFromHost.Descriptor,
/*
* Configuration response processing:
*/
@ -43,66 +33,6 @@ namespace OpenIddict.Server.AspNetCore
* Cryptography response processing:
*/
ProcessJsonResponse<ApplyCryptographyResponseContext>.Descriptor);
/// <summary>
/// Contains the logic responsible of infering the issuer URL from the HTTP request host.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class InferIssuerFromHost : IOpenIddictServerHandler<HandleConfigurationRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleConfigurationRequestContext>()
.AddFilter<RequireHttpRequest>()
// Note: this handler must be invoked after AttachIssuer and before AttachEndpoints.
.UseSingletonHandler<InferIssuerFromHost>()
.SetOrder(OpenIddictServerHandlers.Discovery.AttachIssuer.Descriptor.Order + 500)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleConfigurationRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetHttpRequest();
if (request == null)
{
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.Issuer == null)
{
if (!request.Host.HasValue)
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.Issuer = issuer;
}
return default;
}
}
}
}
}

50
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Exchange.cs

@ -4,11 +4,7 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore;
using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters;
using static OpenIddict.Server.OpenIddictServerEvents;
@ -28,56 +24,12 @@ namespace OpenIddict.Server.AspNetCore
/*
* Token request handling:
*/
EnablePassthroughMode.Descriptor,
EnablePassthroughMode<HandleTokenRequestContext, RequireTokenEndpointPassthroughEnabled>.Descriptor,
/*
* Token response processing:
*/
ProcessJsonResponse<ApplyTokenResponseContext>.Descriptor);
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class EnablePassthroughMode : IOpenIddictServerHandler<HandleTokenRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleTokenRequestContext>()
.AddFilter<RequireTokenEndpointPassthroughEnabled>()
.UseSingletonHandler<EnablePassthroughMode>()
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleTokenRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetHttpRequest();
if (request == null)
{
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
context.SkipRequest();
return default;
}
}
}
}
}

69
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Introspection.cs

@ -4,12 +4,7 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore;
using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters;
using static OpenIddict.Server.OpenIddictServerEvents;
namespace OpenIddict.Server.AspNetCore
@ -24,74 +19,10 @@ namespace OpenIddict.Server.AspNetCore
*/
ExtractGetOrPostRequest<ExtractIntrospectionRequestContext>.Descriptor,
/*
* Introspection request handling:
*/
InferIssuerFromHost.Descriptor,
/*
* Introspection response processing:
*/
ProcessJsonResponse<ApplyIntrospectionResponseContext>.Descriptor);
/// <summary>
/// Contains the logic responsible of infering the issuer URL from the HTTP request host.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class InferIssuerFromHost : IOpenIddictServerHandler<HandleIntrospectionRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleIntrospectionRequestContext>()
.AddFilter<RequireHttpRequest>()
.UseSingletonHandler<InferIssuerFromHost>()
.SetOrder(OpenIddictServerHandlers.Introspection.AttachMetadataClaims.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleIntrospectionRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetHttpRequest();
if (request == null)
{
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.Issuer == null)
{
if (!request.Host.HasValue)
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.Issuer = issuer.AbsoluteUri;
}
return default;
}
}
}
}
}

160
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Serialization.cs

@ -1,160 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/openiddict/openiddict-core for more information concerning
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore;
using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.OpenIddictServerHandlers.Serialization;
namespace OpenIddict.Server.AspNetCore
{
public static partial class OpenIddictServerAspNetCoreHandlers
{
public static class Serialization
{
public static ImmutableArray<OpenIddictServerHandlerDescriptor> DefaultHandlers { get; } = ImmutableArray.Create(
/*
* Token serialization:
*/
InferTokenSerializationIssuerFromHost<SerializeAccessTokenContext>.Descriptor,
InferTokenSerializationIssuerFromHost<SerializeAuthorizationCodeContext>.Descriptor,
InferTokenSerializationIssuerFromHost<SerializeIdentityTokenContext>.Descriptor,
InferTokenSerializationIssuerFromHost<SerializeRefreshTokenContext>.Descriptor,
/*
* Token deserialization:
*/
InferTokenDeserializationIssuerFromHost<DeserializeAccessTokenContext>.Descriptor,
InferTokenDeserializationIssuerFromHost<DeserializeAuthorizationCodeContext>.Descriptor,
InferTokenDeserializationIssuerFromHost<DeserializeIdentityTokenContext>.Descriptor,
InferTokenDeserializationIssuerFromHost<DeserializeRefreshTokenContext>.Descriptor);
}
/// <summary>
/// Contains the logic responsible of infering the issuer URL from the HTTP request host for token deserialization.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class InferTokenSerializationIssuerFromHost<TContext> : IOpenIddictServerHandler<TContext>
where TContext : BaseSerializingContext
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpRequest>()
.UseSingletonHandler<InferTokenSerializationIssuerFromHost<TContext>>()
.SetOrder(AttachIdentityTokenSerializationParameters.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetHttpRequest();
if (request == null)
{
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.Issuer == null)
{
if (!request.Host.HasValue)
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.Issuer = issuer;
}
return default;
}
}
/// <summary>
/// Contains the logic responsible of infering the discovery document issuer URL from the HTTP request host.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class InferTokenDeserializationIssuerFromHost<TContext> : IOpenIddictServerHandler<TContext>
where TContext : BaseDeserializingContext
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpRequest>()
.UseSingletonHandler<InferTokenDeserializationIssuerFromHost<TContext>>()
.SetOrder(AttachIdentityTokenDeserializationParameters.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetHttpRequest();
if (request == null)
{
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.TokenValidationParameters != null && context.TokenValidationParameters.ValidIssuer == null)
{
if (!request.Host.HasValue)
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.TokenValidationParameters.ValidIssuer = issuer.AbsoluteUri;
}
return default;
}
}
}
}

39
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs

@ -45,7 +45,7 @@ namespace OpenIddict.Server.AspNetCore
/*
* Logout request handling:
*/
EnablePassthroughMode.Descriptor,
EnablePassthroughMode<HandleLogoutRequestContext, RequireLogoutEndpointPassthroughEnabled>.Descriptor,
/*
* Logout response processing:
@ -237,43 +237,6 @@ namespace OpenIddict.Server.AspNetCore
}
}
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class EnablePassthroughMode : IOpenIddictServerHandler<HandleLogoutRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleLogoutRequestContext>()
.AddFilter<RequireHttpRequest>()
.AddFilter<RequireLogoutEndpointPassthroughEnabled>()
.UseSingletonHandler<EnablePassthroughMode>()
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleLogoutRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
}
}
/// <summary>
/// Contains the logic responsible of removing cached logout requests from the distributed cache.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.

111
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Userinfo.cs

@ -4,14 +4,9 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore;
using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.OpenIddictServerHandlers.Userinfo;
namespace OpenIddict.Server.AspNetCore
{
@ -29,116 +24,12 @@ namespace OpenIddict.Server.AspNetCore
/*
* Userinfo request handling:
*/
EnablePassthroughMode.Descriptor,
InferIssuerFromHost.Descriptor,
EnablePassthroughMode<HandleUserinfoRequestContext, RequireUserinfoEndpointPassthroughEnabled>.Descriptor,
/*
* Userinfo response processing:
*/
ProcessJsonResponse<ApplyUserinfoResponseContext>.Descriptor);
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class EnablePassthroughMode : IOpenIddictServerHandler<HandleUserinfoRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleUserinfoRequestContext>()
.AddFilter<RequireUserinfoEndpointPassthroughEnabled>()
.UseSingletonHandler<EnablePassthroughMode>()
.SetOrder(AttachIssuer.Descriptor.Order - 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleUserinfoRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetHttpRequest();
if (request == null)
{
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
context.SkipRequest();
return default;
}
}
/// <summary>
/// Contains the logic responsible of infering the issuer URL from the HTTP request host.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class InferIssuerFromHost : IOpenIddictServerHandler<HandleUserinfoRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleUserinfoRequestContext>()
.AddFilter<RequireHttpRequest>()
.UseSingletonHandler<InferIssuerFromHost>()
.SetOrder(AttachIssuer.Descriptor.Order + 500)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleUserinfoRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetHttpRequest();
if (request == null)
{
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.Issuer == null)
{
if (!request.Host.HasValue)
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.Issuer = issuer.AbsoluteUri;
}
return default;
}
}
}
}
}

99
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs

@ -32,14 +32,13 @@ namespace OpenIddict.Server.AspNetCore
* Top-level request processing:
*/
InferEndpointType.Descriptor,
ValidateTransportSecurityRequirement.Descriptor,
ValidateHost.Descriptor)
InferIssuerFromHost.Descriptor,
ValidateTransportSecurityRequirement.Descriptor)
.AddRange(Authentication.DefaultHandlers)
.AddRange(Discovery.DefaultHandlers)
.AddRange(Exchange.DefaultHandlers)
.AddRange(Introspection.DefaultHandlers)
.AddRange(Revocation.DefaultHandlers)
.AddRange(Serialization.DefaultHandlers)
.AddRange(Session.DefaultHandlers)
.AddRange(Userinfo.DefaultHandlers);
@ -136,10 +135,10 @@ namespace OpenIddict.Server.AspNetCore
}
/// <summary>
/// Contains the logic responsible of rejecting OpenID Connect requests that don't use transport security.
/// Contains the logic responsible of infering the issuer URL from the HTTP request host and validating it.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class ValidateTransportSecurityRequirement : IOpenIddictServerHandler<ProcessRequestContext>
public class InferIssuerFromHost : IOpenIddictServerHandler<ProcessRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -147,8 +146,7 @@ namespace OpenIddict.Server.AspNetCore
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessRequestContext>()
.AddFilter<RequireHttpRequest>()
.AddFilter<RequireTransportSecurityRequirementEnabled>()
.UseSingletonHandler<ValidateTransportSecurityRequirement>()
.UseSingletonHandler<InferIssuerFromHost>()
.SetOrder(InferEndpointType.Descriptor.Order + 1_000)
.Build();
@ -174,31 +172,43 @@ namespace OpenIddict.Server.AspNetCore
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
// Don't require that the host be present if the request is not handled by OpenIddict.
if (context.EndpointType == OpenIddictServerEndpointType.Unknown)
// Don't require that the request host be present if the request is not handled
// by an OpenIddict endpoint or if an explicit issuer URL was already set.
if (context.Issuer != null || context.EndpointType == OpenIddictServerEndpointType.Unknown)
{
return default;
}
// Reject authorization requests sent without transport security.
if (!request.IsHttps)
if (!request.Host.HasValue)
{
context.Reject(
error: Errors.InvalidRequest,
description: "This server only accepts HTTPS requests.");
description: "The mandatory 'Host' header is missing.");
return default;
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer) ||
!issuer.IsWellFormedOriginalString())
{
context.Reject(
error: Errors.InvalidRequest,
description: "The specified 'Host' header is invalid.");
return default;
}
context.Issuer = issuer;
return default;
}
}
/// <summary>
/// Contains the logic responsible of ensuring the host can be inferred from the request if none was set in the options.
/// Contains the logic responsible of rejecting OpenID Connect requests that don't use transport security.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class ValidateHost : IOpenIddictServerHandler<ProcessRequestContext>
public class ValidateTransportSecurityRequirement : IOpenIddictServerHandler<ProcessRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -206,8 +216,9 @@ namespace OpenIddict.Server.AspNetCore
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessRequestContext>()
.AddFilter<RequireHttpRequest>()
.UseSingletonHandler<ValidateHost>()
.SetOrder(ValidateTransportSecurityRequirement.Descriptor.Order + 1_000)
.AddFilter<RequireTransportSecurityRequirementEnabled>()
.UseSingletonHandler<ValidateTransportSecurityRequirement>()
.SetOrder(InferEndpointType.Descriptor.Order + 1_000)
.Build();
/// <summary>
@ -232,18 +243,18 @@ namespace OpenIddict.Server.AspNetCore
throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved.");
}
// Don't require that the request host be present if the request is not handled
// by an OpenIddict endpoint or if an explicit issuer URL was set in the options.
if (context.Options.Issuer != null || context.EndpointType == OpenIddictServerEndpointType.Unknown)
// Don't require that the host be present if the request is not handled by OpenIddict.
if (context.EndpointType == OpenIddictServerEndpointType.Unknown)
{
return default;
}
if (!request.Host.HasValue)
// Reject authorization requests sent without transport security.
if (!request.IsHttps)
{
context.Reject(
error: Errors.InvalidRequest,
description: "The mandatory 'Host' header is missing.");
description: "This server only accepts HTTPS requests.");
return default;
}
@ -265,7 +276,7 @@ namespace OpenIddict.Server.AspNetCore
= OpenIddictServerHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpRequest>()
.UseSingletonHandler<ExtractGetOrPostRequest<TContext>>()
.SetOrder(ValidateHost.Descriptor.Order + 1_000)
.SetOrder(ValidateTransportSecurityRequirement.Descriptor.Order + 1_000)
.Build();
/// <summary>
@ -633,6 +644,45 @@ namespace OpenIddict.Server.AspNetCore
}
}
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class EnablePassthroughMode<TContext, TFilter> : IOpenIddictServerHandler<TContext>
where TContext : BaseRequestContext
where TFilter : IOpenIddictServerHandlerFilter<TContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpRequest>()
.AddFilter<TFilter>()
.UseSingletonHandler<EnablePassthroughMode<TContext, TFilter>>()
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
}
}
/// <summary>
/// Contains the logic responsible of processing OpenID Connect responses that must be returned as JSON.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
@ -704,8 +754,7 @@ namespace OpenIddict.Server.AspNetCore
if (!string.IsNullOrEmpty(scheme))
{
var issuer = context.Options.Issuer;
if (issuer == null && !Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out issuer))
if (context.Issuer == null)
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
@ -717,7 +766,7 @@ namespace OpenIddict.Server.AspNetCore
.Append(' ')
.Append(Parameters.Realm)
.Append("=\"")
.Append(issuer.AbsoluteUri)
.Append(context.Issuer.AbsoluteUri)
.Append('"')
.ToString();
}

38
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs

@ -44,7 +44,7 @@ namespace OpenIddict.Server.Owin
/*
* Authorization request handling:
*/
EnablePassthroughMode.Descriptor,
EnablePassthroughMode<HandleAuthorizationRequestContext, RequireAuthorizationEndpointPassthroughEnabled>.Descriptor,
/*
* Authorization response processing:
@ -237,42 +237,6 @@ namespace OpenIddict.Server.Owin
}
}
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class EnablePassthroughMode : IOpenIddictServerHandler<HandleAuthorizationRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleAuthorizationRequestContext>()
.AddFilter<RequireAuthorizationEndpointPassthroughEnabled>()
.UseSingletonHandler<EnablePassthroughMode>()
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleAuthorizationRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
}
}
/// <summary>
/// Contains the logic responsible of removing cached authorization requests from the distributed cache.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.

70
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Discovery.cs

@ -4,13 +4,8 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Owin;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters;
namespace OpenIddict.Server.Owin
{
@ -24,11 +19,6 @@ namespace OpenIddict.Server.Owin
*/
ExtractGetRequest<ExtractConfigurationRequestContext>.Descriptor,
/*
* Configuration request handling:
*/
InferIssuerFromHost.Descriptor,
/*
* Configuration response processing:
*/
@ -43,66 +33,6 @@ namespace OpenIddict.Server.Owin
* Cryptography response processing:
*/
ProcessJsonResponse<ApplyCryptographyResponseContext>.Descriptor);
/// <summary>
/// Contains the logic responsible of infering the issuer URL from the HTTP request host.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class InferIssuerFromHost : IOpenIddictServerHandler<HandleConfigurationRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleConfigurationRequestContext>()
.AddFilter<RequireOwinRequest>()
// Note: this handler must be invoked after AttachIssuer and before AttachEndpoints.
.UseSingletonHandler<InferIssuerFromHost>()
.SetOrder(OpenIddictServerHandlers.Discovery.AttachIssuer.Descriptor.Order + 500)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleConfigurationRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If The OWIN request cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetOwinRequest();
if (request == null)
{
throw new InvalidOperationException("The OWIN request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.Issuer == null)
{
if (string.IsNullOrEmpty(request.Host.Value))
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.Issuer = issuer;
}
return default;
}
}
}
}
}

41
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Exchange.cs

@ -4,10 +4,7 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters;
@ -27,48 +24,12 @@ namespace OpenIddict.Server.Owin
/*
* Token request handling:
*/
EnablePassthroughMode.Descriptor,
EnablePassthroughMode<HandleTokenRequestContext, RequireTokenEndpointPassthroughEnabled>.Descriptor,
/*
* Token response processing:
*/
ProcessJsonResponse<ApplyTokenResponseContext>.Descriptor);
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class EnablePassthroughMode : IOpenIddictServerHandler<HandleTokenRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleTokenRequestContext>()
.AddFilter<RequireTokenEndpointPassthroughEnabled>()
.UseSingletonHandler<EnablePassthroughMode>()
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleTokenRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
}
}
}
}
}

69
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Introspection.cs

@ -4,13 +4,8 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Owin;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters;
namespace OpenIddict.Server.Owin
{
@ -24,74 +19,10 @@ namespace OpenIddict.Server.Owin
*/
ExtractGetOrPostRequest<ExtractIntrospectionRequestContext>.Descriptor,
/*
* Introspection request handling:
*/
InferIssuerFromHost.Descriptor,
/*
* Introspection response processing:
*/
ProcessJsonResponse<ApplyIntrospectionResponseContext>.Descriptor);
/// <summary>
/// Contains the logic responsible of infering the issuer URL from the HTTP request host.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class InferIssuerFromHost : IOpenIddictServerHandler<HandleIntrospectionRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleIntrospectionRequestContext>()
.AddFilter<RequireOwinRequest>()
.UseSingletonHandler<InferIssuerFromHost>()
.SetOrder(OpenIddictServerHandlers.Introspection.AttachMetadataClaims.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleIntrospectionRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If The OWIN request cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetOwinRequest();
if (request == null)
{
throw new InvalidOperationException("The OWIN request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.Issuer == null)
{
if (string.IsNullOrEmpty(request.Host.Value))
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.Issuer = issuer.AbsoluteUri;
}
return default;
}
}
}
}
}

160
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Serialization.cs

@ -1,160 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/openiddict/openiddict-core for more information concerning
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Owin;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.OpenIddictServerHandlers.Serialization;
using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters;
namespace OpenIddict.Server.Owin
{
public static partial class OpenIddictServerOwinHandlers
{
public static class Serialization
{
public static ImmutableArray<OpenIddictServerHandlerDescriptor> DefaultHandlers { get; } = ImmutableArray.Create(
/*
* Token serialization:
*/
InferIssuerFromHostForTokenSerialization<SerializeAccessTokenContext>.Descriptor,
InferIssuerFromHostForTokenSerialization<SerializeAuthorizationCodeContext>.Descriptor,
InferIssuerFromHostForTokenSerialization<SerializeIdentityTokenContext>.Descriptor,
InferIssuerFromHostForTokenSerialization<SerializeRefreshTokenContext>.Descriptor,
/*
* Token deserialization:
*/
InferIssuerFromHostForTokenDeserialization<DeserializeAccessTokenContext>.Descriptor,
InferIssuerFromHostForTokenDeserialization<DeserializeAuthorizationCodeContext>.Descriptor,
InferIssuerFromHostForTokenDeserialization<DeserializeIdentityTokenContext>.Descriptor,
InferIssuerFromHostForTokenDeserialization<DeserializeRefreshTokenContext>.Descriptor);
}
/// <summary>
/// Contains the logic responsible of infering the issuer URL from the HTTP request host for token deserialization.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class InferIssuerFromHostForTokenSerialization<TContext> : IOpenIddictServerHandler<TContext>
where TContext : BaseSerializingContext
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireOwinRequest>()
.UseSingletonHandler<InferIssuerFromHostForTokenSerialization<TContext>>()
.SetOrder(AttachIdentityTokenSerializationParameters.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If The OWIN request cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetOwinRequest();
if (request == null)
{
throw new InvalidOperationException("The OWIN request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.Issuer == null)
{
if (string.IsNullOrEmpty(request.Host.Value))
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.Issuer = issuer;
}
return default;
}
}
/// <summary>
/// Contains the logic responsible of infering the discovery document issuer URL from the HTTP request host.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by ASP.NET Core.
/// </summary>
public class InferIssuerFromHostForTokenDeserialization<TContext> : IOpenIddictServerHandler<TContext>
where TContext : BaseDeserializingContext
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireOwinRequest>()
.UseSingletonHandler<InferIssuerFromHostForTokenDeserialization<TContext>>()
.SetOrder(AttachIdentityTokenDeserializationParameters.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If The OWIN request cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetOwinRequest();
if (request == null)
{
throw new InvalidOperationException("The OWIN request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.TokenValidationParameters != null && context.TokenValidationParameters.ValidIssuer == null)
{
if (string.IsNullOrEmpty(request.Host.Value))
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.TokenValidationParameters.ValidIssuer = issuer.AbsoluteUri;
}
return default;
}
}
}
}

39
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs

@ -43,7 +43,7 @@ namespace OpenIddict.Server.Owin
/*
* Logout request handling:
*/
EnablePassthroughMode.Descriptor,
EnablePassthroughMode<HandleUserinfoRequestContext, RequireLogoutEndpointPassthroughEnabled>.Descriptor,
/*
* Logout response processing:
@ -235,43 +235,6 @@ namespace OpenIddict.Server.Owin
}
}
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class EnablePassthroughMode : IOpenIddictServerHandler<HandleLogoutRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleLogoutRequestContext>()
.AddFilter<RequireOwinRequest>()
.AddFilter<RequireLogoutEndpointPassthroughEnabled>()
.UseSingletonHandler<EnablePassthroughMode>()
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleLogoutRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
}
}
/// <summary>
/// Contains the logic responsible of removing cached logout requests from the distributed cache.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.

114
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Userinfo.cs

@ -4,15 +4,9 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.OpenIddictServerHandlers.Userinfo;
using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlers;
using Owin;
using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters;
namespace OpenIddict.Server.Owin
{
@ -30,116 +24,12 @@ namespace OpenIddict.Server.Owin
/*
* Userinfo request handling:
*/
EnablePassthroughMode.Descriptor,
InferIssuerFromHost.Descriptor,
EnablePassthroughMode<HandleUserinfoRequestContext, RequireUserinfoEndpointPassthroughEnabled>.Descriptor,
/*
* Userinfo response processing:
*/
ProcessJsonResponse<ApplyUserinfoResponseContext>.Descriptor);
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class EnablePassthroughMode : IOpenIddictServerHandler<HandleUserinfoRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleUserinfoRequestContext>()
.AddFilter<RequireUserinfoEndpointPassthroughEnabled>()
.UseSingletonHandler<EnablePassthroughMode>()
.SetOrder(AttachIssuer.Descriptor.Order - 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleUserinfoRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If The OWIN request cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetOwinRequest();
if (request == null)
{
throw new InvalidOperationException("The OWIN request cannot be resolved.");
}
context.SkipRequest();
return default;
}
}
/// <summary>
/// Contains the logic responsible of infering the issuer URL from the HTTP request host.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class InferIssuerFromHost : IOpenIddictServerHandler<HandleUserinfoRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleUserinfoRequestContext>()
.AddFilter<RequireOwinRequest>()
.UseSingletonHandler<InferIssuerFromHost>()
.SetOrder(AttachIssuer.Descriptor.Order + 500)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleUserinfoRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If The OWIN request cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var request = context.Transaction.GetOwinRequest();
if (request == null)
{
throw new InvalidOperationException("The OWIN request cannot be resolved.");
}
// If the issuer was not populated by another handler (e.g from the server options),
// try to infer it from the request scheme/host/path base (which requires HTTP/1.1).
if (context.Issuer == null)
{
if (string.IsNullOrEmpty(request.Host.Value))
{
throw new InvalidOperationException("No host was attached to the HTTP request.");
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer))
{
throw new InvalidOperationException("The issuer address cannot be inferred from the current request.");
}
context.Issuer = issuer.AbsoluteUri;
}
return default;
}
}
}
}
}

92
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs

@ -31,14 +31,13 @@ namespace OpenIddict.Server.Owin
* Top-level request processing:
*/
InferEndpointType.Descriptor,
ValidateTransportSecurityRequirement.Descriptor,
ValidateHost.Descriptor)
InferIssuerFromHost.Descriptor,
ValidateTransportSecurityRequirement.Descriptor)
.AddRange(Authentication.DefaultHandlers)
.AddRange(Discovery.DefaultHandlers)
.AddRange(Exchange.DefaultHandlers)
.AddRange(Introspection.DefaultHandlers)
.AddRange(Revocation.DefaultHandlers)
.AddRange(Serialization.DefaultHandlers)
.AddRange(Session.DefaultHandlers)
.AddRange(Userinfo.DefaultHandlers);
@ -137,10 +136,10 @@ namespace OpenIddict.Server.Owin
}
/// <summary>
/// Contains the logic responsible of rejecting OpenID Connect requests that don't use transport security.
/// Contains the logic responsible of infering the issuer URL from the HTTP request host and validating it.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class ValidateTransportSecurityRequirement : IOpenIddictServerHandler<ProcessRequestContext>
public class InferIssuerFromHost : IOpenIddictServerHandler<ProcessRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -148,8 +147,7 @@ namespace OpenIddict.Server.Owin
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessRequestContext>()
.AddFilter<RequireOwinRequest>()
.AddFilter<RequireTransportSecurityRequirementEnabled>()
.UseSingletonHandler<ValidateTransportSecurityRequirement>()
.UseSingletonHandler<InferIssuerFromHost>()
.SetOrder(InferEndpointType.Descriptor.Order + 1_000)
.Build();
@ -175,18 +173,28 @@ namespace OpenIddict.Server.Owin
throw new InvalidOperationException("The OWIN request cannot be resolved.");
}
// Don't require that the host be present if the request is not handled by OpenIddict.
if (context.EndpointType == OpenIddictServerEndpointType.Unknown)
// Don't require that the request host be present if the request is not handled
// by an OpenIddict endpoint or if an explicit issuer URL was already set.
if (context.Issuer != null || context.EndpointType == OpenIddictServerEndpointType.Unknown)
{
return default;
}
// Reject authorization requests sent without transport security.
if (!request.IsSecure)
if (string.IsNullOrEmpty(request.Host.Value))
{
context.Reject(
error: Errors.InvalidRequest,
description: "This server only accepts HTTPS requests.");
description: "The mandatory 'Host' header is missing.");
return default;
}
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer) ||
!issuer.IsWellFormedOriginalString())
{
context.Reject(
error: Errors.InvalidRequest,
description: "The specified 'Host' header is invalid.");
return default;
}
@ -196,10 +204,10 @@ namespace OpenIddict.Server.Owin
}
/// <summary>
/// Contains the logic responsible of ensuring the host can be inferred from the request if none was set in the options.
/// Contains the logic responsible of rejecting OpenID Connect requests that don't use transport security.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class ValidateHost : IOpenIddictServerHandler<ProcessRequestContext>
public class ValidateTransportSecurityRequirement : IOpenIddictServerHandler<ProcessRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -207,8 +215,9 @@ namespace OpenIddict.Server.Owin
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessRequestContext>()
.AddFilter<RequireOwinRequest>()
.UseSingletonHandler<ValidateHost>()
.SetOrder(ValidateTransportSecurityRequirement.Descriptor.Order + 1_000)
.AddFilter<RequireTransportSecurityRequirementEnabled>()
.UseSingletonHandler<ValidateTransportSecurityRequirement>()
.SetOrder(InferEndpointType.Descriptor.Order + 1_000)
.Build();
/// <summary>
@ -233,18 +242,18 @@ namespace OpenIddict.Server.Owin
throw new InvalidOperationException("The OWIN request cannot be resolved.");
}
// Don't require that the request host be present if the request is not handled
// by an OpenIddict endpoint or if an explicit issuer URL was set in the options.
if (context.Options.Issuer != null || context.EndpointType == OpenIddictServerEndpointType.Unknown)
// Don't require that the host be present if the request is not handled by OpenIddict.
if (context.EndpointType == OpenIddictServerEndpointType.Unknown)
{
return default;
}
if (string.IsNullOrEmpty(request.Host.Value))
// Reject authorization requests sent without transport security.
if (!request.IsSecure)
{
context.Reject(
error: Errors.InvalidRequest,
description: "The mandatory 'Host' header is missing.");
description: "This server only accepts HTTPS requests.");
return default;
}
@ -266,7 +275,7 @@ namespace OpenIddict.Server.Owin
= OpenIddictServerHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireOwinRequest>()
.UseSingletonHandler<ExtractGetOrPostRequest<TContext>>()
.SetOrder(ValidateHost.Descriptor.Order + 1_000)
.SetOrder(ValidateTransportSecurityRequirement.Descriptor.Order + 1_000)
.Build();
/// <summary>
@ -634,6 +643,45 @@ namespace OpenIddict.Server.Owin
}
}
/// <summary>
/// Contains the logic responsible of enabling the pass-through mode for the received request.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.
/// </summary>
public class EnablePassthroughMode<TContext, TFilter> : IOpenIddictServerHandler<TContext>
where TContext : BaseRequestContext
where TFilter : IOpenIddictServerHandlerFilter<TContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireOwinRequest>()
.AddFilter<TFilter>()
.UseSingletonHandler<EnablePassthroughMode<TContext, TFilter>>()
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
}
}
/// <summary>
/// Contains the logic responsible of processing OpenID Connect responses that must be returned as JSON.
/// Note: this handler is not used when the OpenID Connect request is not initially handled by OWIN.

5
src/OpenIddict.Server/OpenIddictServerEvents.Discovery.cs

@ -99,11 +99,6 @@ namespace OpenIddict.Server
/// </summary>
public Uri UserinfoEndpoint { get; set; }
/// <summary>
/// Gets or sets the issuer address.
/// </summary>
public Uri Issuer { get; set; }
/// <summary>
/// Gets the list of claims supported by the authorization server.
/// </summary>

6
src/OpenIddict.Server/OpenIddictServerEvents.Introspection.cs

@ -105,12 +105,6 @@ namespace OpenIddict.Server
/// </summary>
public DateTimeOffset? IssuedAt { get; set; }
/// <summary>
/// Gets or sets the "iss" claim
/// returned to the caller, if applicable.
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// Gets or sets the "nbf" claim
/// returned to the caller, if applicable.

5
src/OpenIddict.Server/OpenIddictServerEvents.Serialization.cs

@ -48,11 +48,6 @@ namespace OpenIddict.Server
/// </summary>
public JsonWebTokenHandler SecurityTokenHandler { get; set; }
/// <summary>
/// Gets or sets the issuer address.
/// </summary>
public Uri Issuer { get; set; }
/// <summary>
/// Gets or sets the token returned to the client application.
/// </summary>

5
src/OpenIddict.Server/OpenIddictServerEvents.Userinfo.cs

@ -123,11 +123,6 @@ namespace OpenIddict.Server
/// </summary>
public string GivenName { get; set; }
/// <summary>
/// Gets or sets the value used for the "iss" claim.
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// Gets or sets the value used for the "phone_number" claim.
/// Note: this value should only be populated if the "phone"

9
src/OpenIddict.Server/OpenIddictServerEvents.cs

@ -33,6 +33,15 @@ namespace OpenIddict.Server
/// </summary>
public OpenIddictServerTransaction Transaction { get; }
/// <summary>
/// Gets or sets the issuer address associated with the current transaction, if available.
/// </summary>
public Uri Issuer
{
get => Transaction.Issuer;
set => Transaction.Issuer = value;
}
/// <summary>
/// Gets or sets the endpoint type that handled the request, if applicable.
/// </summary>

40
src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs

@ -40,7 +40,6 @@ namespace OpenIddict.Server
/*
* Configuration request handling:
*/
AttachIssuer.Descriptor,
AttachEndpoints.Descriptor,
AttachGrantTypes.Descriptor,
AttachResponseModes.Descriptor,
@ -357,43 +356,6 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Contains the logic responsible of attaching the issuer URL to the provider discovery document.
/// </summary>
public class AttachIssuer : IOpenIddictServerHandler<HandleConfigurationRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleConfigurationRequestContext>()
.UseSingletonHandler<AttachIssuer>()
.SetOrder(int.MinValue + 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleConfigurationRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Options.Issuer != null)
{
context.Issuer = context.Options.Issuer;
}
return default;
}
}
/// <summary>
/// Contains the logic responsible of attaching the endpoint URLs to the provider discovery document.
/// </summary>
@ -405,7 +367,7 @@ namespace OpenIddict.Server
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleConfigurationRequestContext>()
.UseSingletonHandler<AttachEndpoints>()
.SetOrder(AttachIssuer.Descriptor.Order + 1_000)
.SetOrder(int.MaxValue - 100_000)
.Build();
/// <summary>

3
src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs

@ -270,7 +270,7 @@ namespace OpenIddict.Server
var response = new OpenIddictResponse
{
[Claims.Active] = true,
[Claims.Issuer] = notification.Issuer,
[Claims.Issuer] = notification.Issuer?.AbsoluteUri,
[Claims.Username] = notification.Username,
[Claims.Subject] = notification.Subject,
[Claims.Scope] = string.Join(" ", notification.Scopes),
@ -984,7 +984,6 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
context.Issuer = context.Options.Issuer?.AbsoluteUri;
context.TokenId = context.Principal.GetTokenId();
context.TokenUsage = context.Principal.GetTokenUsage();
context.Subject = context.Principal.GetClaim(Claims.Subject);

12
src/OpenIddict.Server/OpenIddictServerHandlers.Serialization.cs

@ -285,7 +285,6 @@ namespace OpenIddict.Server
context.EncryptingCredentials = context.Options.EncryptionCredentials.FirstOrDefault(
credentials => credentials.Key is SymmetricSecurityKey);
context.Issuer = context.Options.Issuer;
context.SecurityTokenHandler = context.Options.AccessTokenHandler;
context.SigningCredentials = context.Options.SigningCredentials.FirstOrDefault(
credentials => credentials.Key is SymmetricSecurityKey) ?? context.Options.SigningCredentials.First();
@ -333,7 +332,6 @@ namespace OpenIddict.Server
}
context.EncryptingCredentials = context.Options.EncryptionCredentials[0];
context.Issuer = context.Options.Issuer;
context.SecurityTokenHandler = context.Options.AuthorizationCodeHandler;
context.SigningCredentials = context.Options.SigningCredentials.FirstOrDefault(
credentials => credentials.Key is SymmetricSecurityKey) ?? context.Options.SigningCredentials.First();
@ -375,7 +373,6 @@ namespace OpenIddict.Server
throw new InvalidOperationException("No suitable signing credentials could be found.");
}
context.Issuer = context.Options.Issuer;
context.SecurityTokenHandler = context.Options.IdentityTokenHandler;
context.SigningCredentials = context.Options.SigningCredentials.First(
credentials => credentials.Key is AsymmetricSecurityKey);
@ -423,7 +420,6 @@ namespace OpenIddict.Server
}
context.EncryptingCredentials = context.Options.EncryptionCredentials[0];
context.Issuer = context.Options.Issuer;
context.SecurityTokenHandler = context.Options.AuthorizationCodeHandler;
context.SigningCredentials = context.Options.SigningCredentials.FirstOrDefault(
credentials => credentials.Key is SymmetricSecurityKey) ?? context.Options.SigningCredentials.First();
@ -469,7 +465,7 @@ namespace OpenIddict.Server
context.TokenValidationParameters.TokenDecryptionKeys = context.Options.EncryptionCredentials
.Select(credentials => credentials.Key)
.Where(key => key is SymmetricSecurityKey);
context.TokenValidationParameters.ValidIssuer = context.Options.Issuer?.AbsoluteUri;
context.TokenValidationParameters.ValidIssuer = context.Issuer?.AbsoluteUri;
context.TokenValidationParameters.ValidateAudience = false;
context.TokenValidationParameters.ValidateLifetime = false;
@ -513,7 +509,7 @@ namespace OpenIddict.Server
context.TokenValidationParameters.RoleClaimType = Claims.Role;
context.TokenValidationParameters.TokenDecryptionKeys = context.Options.EncryptionCredentials
.Select(credentials => credentials.Key);
context.TokenValidationParameters.ValidIssuer = context.Options.Issuer?.AbsoluteUri;
context.TokenValidationParameters.ValidIssuer = context.Issuer?.AbsoluteUri;
context.TokenValidationParameters.ValidateAudience = false;
context.TokenValidationParameters.ValidateLifetime = false;
@ -556,7 +552,7 @@ namespace OpenIddict.Server
.OfType<AsymmetricSecurityKey>();
context.TokenValidationParameters.NameClaimType = Claims.Name;
context.TokenValidationParameters.RoleClaimType = Claims.Role;
context.TokenValidationParameters.ValidIssuer = context.Options.Issuer?.AbsoluteUri;
context.TokenValidationParameters.ValidIssuer = context.Issuer?.AbsoluteUri;
context.TokenValidationParameters.ValidateAudience = false;
context.TokenValidationParameters.ValidateLifetime = false;
@ -600,7 +596,7 @@ namespace OpenIddict.Server
context.TokenValidationParameters.RoleClaimType = Claims.Role;
context.TokenValidationParameters.TokenDecryptionKeys = context.Options.EncryptionCredentials
.Select(credentials => credentials.Key);
context.TokenValidationParameters.ValidIssuer = context.Options.Issuer?.AbsoluteUri;
context.TokenValidationParameters.ValidIssuer = context.Issuer?.AbsoluteUri;
context.TokenValidationParameters.ValidateAudience = false;
context.TokenValidationParameters.ValidateLifetime = false;

42
src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs

@ -44,7 +44,6 @@ namespace OpenIddict.Server
/*
* Userinfo request handling:
*/
AttachIssuer.Descriptor,
AttachPrincipal.Descriptor,
AttachAudiences.Descriptor,
AttachClaims.Descriptor);
@ -264,7 +263,7 @@ namespace OpenIddict.Server
[Claims.EmailVerified] = notification.EmailVerified,
[Claims.FamilyName] = notification.FamilyName,
[Claims.GivenName] = notification.GivenName,
[Claims.Issuer] = notification.Issuer,
[Claims.Issuer] = notification.Issuer?.AbsoluteUri,
[Claims.PhoneNumber] = notification.PhoneNumber,
[Claims.PhoneNumberVerified] = notification.PhoneNumberVerified,
[Claims.PreferredUsername] = notification.PreferredUsername,
@ -498,43 +497,6 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Contains the logic responsible of attaching the issuer URL to the userinfo response.
/// </summary>
public class AttachIssuer : IOpenIddictServerHandler<HandleUserinfoRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleUserinfoRequestContext>()
.UseSingletonHandler<AttachIssuer>()
.SetOrder(AttachPrincipal.Descriptor.Order + 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleUserinfoRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Options.Issuer != null)
{
context.Issuer = context.Options.Issuer.AbsoluteUri;
}
return default;
}
}
/// <summary>
/// Contains the logic responsible of attaching the audiences to the userinfo response.
/// </summary>
@ -546,7 +508,7 @@ namespace OpenIddict.Server
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleUserinfoRequestContext>()
.UseSingletonHandler<AttachAudiences>()
.SetOrder(AttachIssuer.Descriptor.Order + 100_000)
.SetOrder(AttachPrincipal.Descriptor.Order + 1_000)
.Build();
/// <summary>

1
src/OpenIddict.Server/OpenIddictServerProvider.cs

@ -38,6 +38,7 @@ namespace OpenIddict.Server
public ValueTask<OpenIddictServerTransaction> CreateTransactionAsync()
=> new ValueTask<OpenIddictServerTransaction>(new OpenIddictServerTransaction
{
Issuer = _options.CurrentValue.Issuer,
Logger = _logger,
Options = _options.CurrentValue
});

5
src/OpenIddict.Server/OpenIddictServerTransaction.cs

@ -21,6 +21,11 @@ namespace OpenIddict.Server
/// </summary>
public OpenIddictServerEndpointType EndpointType { get; set; }
/// <summary>
/// Gets or sets the issuer address associated with the current transaction, if available.
/// </summary>
public Uri Issuer { get; set; }
/// <summary>
/// Gets or sets the logger associated with the current request.
/// </summary>

Loading…
Cancel
Save