From 10cf3794b3aca1865e98511ef0576207ebbdbc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Tue, 10 Sep 2019 14:51:52 +0200 Subject: [PATCH] Update the authorization/logout validation/handling events to expose the ClaimsPrincipal resolved from id_token_hint --- .../OpenIddictServerEvents.Authentication.cs | 14 ++++ .../OpenIddictServerEvents.Session.cs | 19 +++-- ...OpenIddictServerHandlers.Authentication.cs | 47 +++++++++++- .../OpenIddictServerHandlers.Session.cs | 76 ++++++++++++++----- 4 files changed, 131 insertions(+), 25 deletions(-) diff --git a/src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs index fda22c03..37e7904c 100644 --- a/src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs +++ b/src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs @@ -76,6 +76,13 @@ namespace OpenIddict.Server RedirectUri = address; } + + /// + /// Gets or sets the security principal extracted from the id_token_hint, if available. + /// Note: the principal may not represent the user currently logged in, + /// so additional validation is strongly encouraged when using this property. + /// + public ClaimsPrincipal IdentityTokenHintPrincipal { get; set; } } /// @@ -91,6 +98,13 @@ namespace OpenIddict.Server : base(transaction) { } + + /// + /// Gets or sets the security principal extracted from the id_token_hint, if available. + /// Note: the principal may not represent the user currently logged in, + /// so additional validation is strongly encouraged when using this property. + /// + public ClaimsPrincipal IdentityTokenHintPrincipal { get; set; } } /// diff --git a/src/OpenIddict.Server/OpenIddictServerEvents.Session.cs b/src/OpenIddict.Server/OpenIddictServerEvents.Session.cs index 2682256b..bcb96db8 100644 --- a/src/OpenIddict.Server/OpenIddictServerEvents.Session.cs +++ b/src/OpenIddict.Server/OpenIddictServerEvents.Session.cs @@ -5,6 +5,7 @@ */ using System; +using System.Security.Claims; using JetBrains.Annotations; namespace OpenIddict.Server @@ -68,6 +69,13 @@ namespace OpenIddict.Server PostLogoutRedirectUri = address; } + + /// + /// Gets or sets the security principal extracted from the id_token_hint, if available. + /// Note: the principal may not represent the user currently logged in, + /// so additional validation is strongly encouraged when using this property. + /// + public ClaimsPrincipal IdentityTokenHintPrincipal { get; set; } } /// @@ -85,14 +93,11 @@ namespace OpenIddict.Server } /// - /// Gets a boolean indicating whether the logout request should be processed. - /// - public bool IsLogoutAllowed { get; private set; } - - /// - /// Allow the logout request to be processed. + /// Gets or sets the security principal extracted from the id_token_hint, if available. + /// Note: the principal may not represent the user currently logged in, + /// so additional validation is strongly encouraged when using this property. /// - public void ProcessLogout() => IsLogoutAllowed = true; + public ClaimsPrincipal IdentityTokenHintPrincipal { get; set; } } /// diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs index 76705003..b8178226 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.Security.Claims; using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; @@ -55,6 +56,11 @@ namespace OpenIddict.Server ValidateGrantTypePermissions.Descriptor, ValidateScopePermissions.Descriptor, + /* + * Authorization request handling: + */ + AttachIdentityTokenHintPrincipal.Descriptor, + /* * Authorization response processing: */ @@ -1027,7 +1033,9 @@ namespace OpenIddict.Server // Note: the expiration date associated with an identity token used as an id_token_hint is deliberately ignored. - // Store the security principal extracted from the identity token as an environment property. + // Attach the security principal extracted from the identity token to the + // validation context and store it as an environment property. + context.IdentityTokenHintPrincipal = notification.Principal; context.Transaction.Properties[Properties.AmbientPrincipal] = notification.Principal; } } @@ -1541,6 +1549,43 @@ namespace OpenIddict.Server } } + /// + /// Contains the logic responsible of attaching the principal extracted from the id_token_hint to the event context. + /// + public class AttachIdentityTokenHintPrincipal : IOpenIddictServerHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictServerHandlerDescriptor Descriptor { get; } + = OpenIddictServerHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(int.MinValue + 100_000) + .Build(); + + /// + /// 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] HandleAuthorizationRequestContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (context.Transaction.Properties.TryGetValue(Properties.AmbientPrincipal, out var principal)) + { + context.IdentityTokenHintPrincipal ??= (ClaimsPrincipal) principal; + } + + return default; + } + } + /// /// Contains the logic responsible of inferring the redirect URL /// used to send the response back to the client application. diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs index 9ece230a..f74f3f54 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Immutable; +using System.Security.Claims; using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; @@ -40,6 +41,11 @@ namespace OpenIddict.Server ValidateIdTokenHint.Descriptor, ValidateClientPostLogoutRedirectUri.Descriptor, + /* + * Logout request handling: + */ + AttachIdentityTokenHintPrincipal.Descriptor, + /* * Logout response processing: */ @@ -255,26 +261,23 @@ namespace OpenIddict.Server return; } - if (notification.IsLogoutAllowed) + var @event = new ProcessSignoutContext(context.Transaction) { - var @event = new ProcessSignoutContext(context.Transaction) - { - Response = new OpenIddictResponse() - }; + Response = new OpenIddictResponse() + }; - await _provider.DispatchAsync(@event); + await _provider.DispatchAsync(@event); - if (@event.IsRequestHandled) - { - context.HandleRequest(); - return; - } + if (@event.IsRequestHandled) + { + context.HandleRequest(); + return; + } - else if (@event.IsRequestSkipped) - { - context.SkipRequest(); - return; - } + else if (@event.IsRequestSkipped) + { + context.SkipRequest(); + return; } throw new InvalidOperationException(new StringBuilder() @@ -459,7 +462,9 @@ namespace OpenIddict.Server // Note: the expiration date associated with an identity token used as an id_token_hint is deliberately ignored. - // Store the security principal extracted from the identity token as an environment property. + // Attach the security principal extracted from the identity token to the + // validation context and store it as an environment property. + context.IdentityTokenHintPrincipal = notification.Principal; context.Transaction.Properties[Properties.AmbientPrincipal] = notification.Principal; } } @@ -549,6 +554,43 @@ namespace OpenIddict.Server } } + /// + /// Contains the logic responsible of attaching the principal extracted from the id_token_hint to the event context. + /// + public class AttachIdentityTokenHintPrincipal : IOpenIddictServerHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictServerHandlerDescriptor Descriptor { get; } + = OpenIddictServerHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(int.MinValue + 100_000) + .Build(); + + /// + /// 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] HandleLogoutRequestContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (context.Transaction.Properties.TryGetValue(Properties.AmbientPrincipal, out var principal)) + { + context.IdentityTokenHintPrincipal ??= (ClaimsPrincipal) principal; + } + + return default; + } + } + /// /// Contains the logic responsible of inferring the redirect URL /// used to send the response back to the client application.