From b22a861757844121cec65b9279ee50cdb186bcda Mon Sep 17 00:00:00 2001 From: Ray Luo Date: Sun, 8 Feb 2026 23:27:13 -0800 Subject: [PATCH 1/4] Update OnBeforeTokenAcquisitionForOnBehalfOf event to use ClaimsPrincipal from token In PR #3712 changed the usage of user to userHint, but based on the logic at the beginning of the changed method, the single source of truth in terms of OBO shall be derived from tokenUsedToCallTheWebApi. This change constructs a ClaimsPrincipal from the token string and preserves the BootstrapContext for use in event handlers. --- .../TokenAcquisition.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs index 060737a84..069f97b43 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs @@ -1255,7 +1255,23 @@ private void NotifyCertificateSelection( { if (addInOptions != null) { - await addInOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(builder, tokenAcquisitionOptions, userHint!).ConfigureAwait(false); + ClaimsPrincipal? principalToUse; + + // Create ClaimsPrincipal from the token if available, otherwise pass null + if (!string.IsNullOrEmpty(tokenUsedToCallTheWebApi)) + { + var handler = new JwtSecurityTokenHandler(); + var jwtToken = handler.ReadJwtToken(tokenUsedToCallTheWebApi); + var identity = new CaseSensitiveClaimsIdentity(jwtToken.Claims); + identity.BootstrapContext = tokenUsedToCallTheWebApi; + principalToUse = new ClaimsPrincipal(identity); + } + else + { + principalToUse = null; + } + + await addInOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(builder, tokenAcquisitionOptions, principalToUse!).ConfigureAwait(false); } AddFmiPathForSignedAssertionIfNeeded(tokenAcquisitionOptions, builder); From f8f7ef4d754d95de455ce6df9b000ad35f345a9b Mon Sep 17 00:00:00 2001 From: trwalke Date: Mon, 9 Feb 2026 22:17:34 -0800 Subject: [PATCH 2/4] Adding DTO for OBO event --- .../OnBehalfOfEventArgs.cs | 25 +++++++++++++++++++ .../net10.0/InternalAPI.Unshipped.txt | 4 +-- .../PublicAPI/net10.0/PublicAPI.Unshipped.txt | 10 ++++++-- .../net462/InternalAPI.Unshipped.txt | 4 +-- .../PublicAPI/net462/PublicAPI.Unshipped.txt | 10 ++++++-- .../net472/InternalAPI.Unshipped.txt | 4 +-- .../PublicAPI/net472/PublicAPI.Unshipped.txt | 10 ++++++-- .../net8.0/InternalAPI.Unshipped.txt | 4 +-- .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 10 ++++++-- .../net9.0/InternalAPI.Unshipped.txt | 4 +-- .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 10 ++++++-- .../netstandard2.0/InternalAPI.Unshipped.txt | 4 +-- .../netstandard2.0/PublicAPI.Unshipped.txt | 10 ++++++-- .../TokenAcquisition.cs | 20 ++++----------- .../TokenAcquisitionExtensionOptions.cs | 8 +++--- .../TokenAcquisitionExtensions.cs | 10 ++++---- .../AuthorizeForScopesAttribute.cs | 2 +- ...tionsAuthenticationHttpContextExtension.cs | 2 +- .../AuthorizationHeaderProviderTests.cs | 5 ++-- .../TokenAcquisitionAddInTests.cs | 5 ++-- 20 files changed, 106 insertions(+), 55 deletions(-) create mode 100644 src/Microsoft.Identity.Web.TokenAcquisition/OnBehalfOfEventArgs.cs diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/OnBehalfOfEventArgs.cs b/src/Microsoft.Identity.Web.TokenAcquisition/OnBehalfOfEventArgs.cs new file mode 100644 index 000000000..2e29e3512 --- /dev/null +++ b/src/Microsoft.Identity.Web.TokenAcquisition/OnBehalfOfEventArgs.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Security.Claims; + +namespace Microsoft.Identity.Web +{ + /// + /// Event arguments for on-behalf-of token acquisition operations. + /// Contains context information about the user and additional data for the token request. + /// + public class OnBehalfOfEventArgs + { + /// + /// Gets or sets the claims principal representing the user for whom the token is being acquired. + /// This is the claims principal into the the api + /// + public ClaimsPrincipal? User { get; set; } + + /// + /// Gets or sets additional context information for the token acquisition operation. + /// + public string? UserAssertionToken { get; set; } + } +} diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net10.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net10.0/InternalAPI.Unshipped.txt index a238605bc..17b84f948 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net10.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net10.0/InternalAPI.Unshipped.txt @@ -1,7 +1,7 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! static Microsoft.Identity.Web.ConfidentialClientApplicationBuilderExtension.Logger.UsingCertThumbprint(Microsoft.Extensions.Logging.ILogger! logger, string? certThumbprint) -> void static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net10.0/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net10.0/PublicAPI.Unshipped.txt index 9833e6abf..cc0306eaf 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net10.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net10.0/PublicAPI.Unshipped.txt @@ -1,7 +1,13 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync +Microsoft.Identity.Web.OnBehalfOfEventArgs +Microsoft.Identity.Web.OnBehalfOfEventArgs.OnBehalfOfEventArgs() -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.get -> System.Security.Claims.ClaimsPrincipal? +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.set -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.get -> string? +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.set -> void Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOfAsync -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync? -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt index a238605bc..17b84f948 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt @@ -1,7 +1,7 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! static Microsoft.Identity.Web.ConfidentialClientApplicationBuilderExtension.Logger.UsingCertThumbprint(Microsoft.Extensions.Logging.ILogger! logger, string? certThumbprint) -> void static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/PublicAPI.Unshipped.txt index 9833e6abf..cc0306eaf 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -1,7 +1,13 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync +Microsoft.Identity.Web.OnBehalfOfEventArgs +Microsoft.Identity.Web.OnBehalfOfEventArgs.OnBehalfOfEventArgs() -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.get -> System.Security.Claims.ClaimsPrincipal? +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.set -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.get -> string? +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.set -> void Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOfAsync -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync? -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt index a238605bc..17b84f948 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt @@ -1,7 +1,7 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! static Microsoft.Identity.Web.ConfidentialClientApplicationBuilderExtension.Logger.UsingCertThumbprint(Microsoft.Extensions.Logging.ILogger! logger, string? certThumbprint) -> void static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/PublicAPI.Unshipped.txt index 9833e6abf..cc0306eaf 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,7 +1,13 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync +Microsoft.Identity.Web.OnBehalfOfEventArgs +Microsoft.Identity.Web.OnBehalfOfEventArgs.OnBehalfOfEventArgs() -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.get -> System.Security.Claims.ClaimsPrincipal? +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.set -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.get -> string? +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.set -> void Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOfAsync -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync? -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/InternalAPI.Unshipped.txt index a238605bc..b8b6d76d8 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/InternalAPI.Unshipped.txt @@ -1,7 +1,5 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! -static Microsoft.Identity.Web.ConfidentialClientApplicationBuilderExtension.Logger.UsingCertThumbprint(Microsoft.Extensions.Logging.ILogger! logger, string? certThumbprint) -> void +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 9833e6abf..cc0306eaf 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1,7 +1,13 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync +Microsoft.Identity.Web.OnBehalfOfEventArgs +Microsoft.Identity.Web.OnBehalfOfEventArgs.OnBehalfOfEventArgs() -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.get -> System.Security.Claims.ClaimsPrincipal? +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.set -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.get -> string? +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.set -> void Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOfAsync -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync? -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/InternalAPI.Unshipped.txt index a238605bc..17b84f948 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/InternalAPI.Unshipped.txt @@ -1,7 +1,7 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! static Microsoft.Identity.Web.ConfidentialClientApplicationBuilderExtension.Logger.UsingCertThumbprint(Microsoft.Extensions.Logging.ILogger! logger, string? certThumbprint) -> void static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/PublicAPI.Unshipped.txt index 9833e6abf..cc0306eaf 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -1,7 +1,13 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync +Microsoft.Identity.Web.OnBehalfOfEventArgs +Microsoft.Identity.Web.OnBehalfOfEventArgs.OnBehalfOfEventArgs() -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.get -> System.Security.Claims.ClaimsPrincipal? +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.set -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.get -> string? +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.set -> void Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOfAsync -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync? -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt index a238605bc..17b84f948 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt @@ -1,7 +1,7 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! static Microsoft.Identity.Web.ConfidentialClientApplicationBuilderExtension.Logger.UsingCertThumbprint(Microsoft.Extensions.Logging.ILogger! logger, string? certThumbprint) -> void static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 9833e6abf..cc0306eaf 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,7 +1,13 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync +Microsoft.Identity.Web.OnBehalfOfEventArgs +Microsoft.Identity.Web.OnBehalfOfEventArgs.OnBehalfOfEventArgs() -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.get -> System.Security.Claims.ClaimsPrincipal? +Microsoft.Identity.Web.OnBehalfOfEventArgs.User.set -> void +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.get -> string? +Microsoft.Identity.Web.OnBehalfOfEventArgs.UserAssertionToken.set -> void Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOfAsync -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync? -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void -virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> System.Threading.Tasks.Task! +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> void +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, Microsoft.Identity.Web.OnBehalfOfEventArgs! eventArgs) -> System.Threading.Tasks.Task! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs index 069f97b43..fdbb46607 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs @@ -1255,23 +1255,13 @@ private void NotifyCertificateSelection( { if (addInOptions != null) { - ClaimsPrincipal? principalToUse; - - // Create ClaimsPrincipal from the token if available, otherwise pass null - if (!string.IsNullOrEmpty(tokenUsedToCallTheWebApi)) - { - var handler = new JwtSecurityTokenHandler(); - var jwtToken = handler.ReadJwtToken(tokenUsedToCallTheWebApi); - var identity = new CaseSensitiveClaimsIdentity(jwtToken.Claims); - identity.BootstrapContext = tokenUsedToCallTheWebApi; - principalToUse = new ClaimsPrincipal(identity); - } - else + var eventArgs = new OnBehalfOfEventArgs { - principalToUse = null; - } + User = userHint, + UserAssertionToken = tokenUsedToCallTheWebApi + }; - await addInOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(builder, tokenAcquisitionOptions, principalToUse!).ConfigureAwait(false); + await addInOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(builder, tokenAcquisitionOptions, eventArgs).ConfigureAwait(false); } AddFmiPathForSignedAssertionIfNeeded(tokenAcquisitionOptions, builder); diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs index 0d0ca0cb4..29f08d24b 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs @@ -59,23 +59,23 @@ internal void InvokeOnBeforeTokenAcquisitionForApp(AcquireTokenForClientParamete /// internal async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(AcquireTokenOnBehalfOfParameterBuilder builder, AcquireTokenOptions? acquireTokenOptions, - ClaimsPrincipal user) + OnBehalfOfEventArgs eventArgs) { // Run the async event if it is not null if (OnBeforeTokenAcquisitionForOnBehalfOfAsync != null) { // (cannot directly await an async event because events are not tasks - // they are multicast delegates that invoke handlers, but don’t return values to the publisher, + // they are multicast delegates that invoke handlers, but don't return values to the publisher, // nor do they support awaiting natively var invocationList = OnBeforeTokenAcquisitionForOnBehalfOfAsync.GetInvocationList(); var tasks = invocationList .Cast() - .Select(handler => handler(builder, acquireTokenOptions, user)); + .Select(handler => handler(builder, acquireTokenOptions, eventArgs)); await Task.WhenAll(tasks); } // Run the sync event if it is not null. - OnBeforeTokenAcquisitionForOnBehalfOf?.Invoke(builder, acquireTokenOptions, user); + OnBeforeTokenAcquisitionForOnBehalfOf?.Invoke(builder, acquireTokenOptions, eventArgs); } /// diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs index 28035d901..74d3cb32d 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs @@ -32,18 +32,18 @@ namespace Microsoft.Identity.Web public delegate Task BeforeTokenAcquisitionForTestUserAsync(AcquireTokenByUsernameAndPasswordConfidentialParameterBuilder builder, AcquireTokenOptions? acquireTokenOptions, ClaimsPrincipal user); /// - /// Signature for token acquisition extensions that act on the request builder, for on-behalf-of flow (Async version). + /// Signature for token acquisition extensions that act on the request builder, for on-behalf-of flow. /// /// Builder /// Token acquisition options for the request. Can be null. - /// User claims. - public delegate void BeforeTokenAcquisitionForOnBehalfOf(AcquireTokenOnBehalfOfParameterBuilder builder, AcquireTokenOptions? acquireTokenOptions, ClaimsPrincipal user); + /// Event arguments containing user claims and additional context information. + public delegate void BeforeTokenAcquisitionForOnBehalfOf(AcquireTokenOnBehalfOfParameterBuilder builder, AcquireTokenOptions? acquireTokenOptions, OnBehalfOfEventArgs eventArgs); /// /// Signature for token acquisition extensions that act on the request builder, for on-behalf-of flow (Async version). /// /// Builder /// Token acquisition options for the request. Can be null. - /// User claims. - public delegate Task BeforeTokenAcquisitionForOnBehalfOfAsync(AcquireTokenOnBehalfOfParameterBuilder builder, AcquireTokenOptions? acquireTokenOptions, ClaimsPrincipal user); + /// Event arguments containing user claims and additional context information. + public delegate Task BeforeTokenAcquisitionForOnBehalfOfAsync(AcquireTokenOnBehalfOfParameterBuilder builder, AcquireTokenOptions? acquireTokenOptions, OnBehalfOfEventArgs eventArgs); } diff --git a/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs b/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs index 540768a73..93e392698 100644 --- a/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs +++ b/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs @@ -53,7 +53,7 @@ public class AuthorizeForScopesAttribute : ExceptionFilterAttribute /// /// Handles the . /// - /// Context provided by ASP.NET Core. + /// UserAssertionToken provided by ASP.NET Core. public override void OnException(ExceptionContext context) { if (context != null) diff --git a/src/Microsoft.Identity.Web/AzureFunctionsAuthenticationHttpContextExtension.cs b/src/Microsoft.Identity.Web/AzureFunctionsAuthenticationHttpContextExtension.cs index 22cba6bb1..876db1328 100644 --- a/src/Microsoft.Identity.Web/AzureFunctionsAuthenticationHttpContextExtension.cs +++ b/src/Microsoft.Identity.Web/AzureFunctionsAuthenticationHttpContextExtension.cs @@ -20,7 +20,7 @@ public static class AzureFunctionsAuthenticationHttpContextExtension /// Calling this method from your Azure function validates the token and exposes the identity of the user or app on behalf of which your function is called, /// in the HttpContext.User member, where your function can make use of it. /// - /// The current HTTP Context, such as req.HttpContext. + /// The current HTTP UserAssertionToken, such as req.HttpContext. /// A task indicating success or failure. In case of failure . public static async Task<(bool, IActionResult?)> AuthenticateAzureFunctionAsync( this HttpContext httpContext) diff --git a/tests/Microsoft.Identity.Web.Test/AuthorizationHeaderProviderTests.cs b/tests/Microsoft.Identity.Web.Test/AuthorizationHeaderProviderTests.cs index 5cbab4b50..940bf6b54 100644 --- a/tests/Microsoft.Identity.Web.Test/AuthorizationHeaderProviderTests.cs +++ b/tests/Microsoft.Identity.Web.Test/AuthorizationHeaderProviderTests.cs @@ -42,10 +42,11 @@ public async Task LongRunningSessionForDefaultAuthProviderForUserDefaultKeyTest( // so the test can observe if the service provider is set in the extra parameters tokenAcquirerFactory.Services.Configure(options => { - options.OnBeforeTokenAcquisitionForOnBehalfOf += (builder, options, user) => + options.OnBeforeTokenAcquisitionForOnBehalfOf += (builder, options, args) => { //verify that the ClaimsPrincipal passed in the event is the same as the one passed to CreateAuthorizationHeaderForUserAsync and that the BootstrapContext is preserved - Assert.Equal(((CaseSensitiveClaimsIdentity)claimsPrincipal.Identity!).BootstrapContext, ((CaseSensitiveClaimsIdentity)user.Identity!).BootstrapContext); + Assert.Equal(((CaseSensitiveClaimsIdentity)claimsPrincipal.Identity!).BootstrapContext, ((CaseSensitiveClaimsIdentity)args?.User?.Identity!).BootstrapContext); + Assert.Equal(((CaseSensitiveClaimsIdentity)claimsPrincipal.Identity!).BootstrapContext, args.UserAssertionToken); }; }); IServiceProvider serviceProvider = tokenAcquirerFactory.Build(); diff --git a/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs b/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs index 2148e03ce..0956a4d2b 100644 --- a/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs +++ b/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs @@ -171,7 +171,7 @@ public async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOf_InvokesEvent() extension.OnBeforeTokenRequestHandler = (request) => { eventInvoked = true; - request.BodyParameters.Add("x-ms-user", user.FindFirst("user")?.Value); + request.BodyParameters.Add("x-ms-user", user?.User?.FindFirst("user")?.Value); return Task.CompletedTask; }; @@ -186,7 +186,8 @@ public async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOf_InvokesEvent() })); // Act - await options.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(builder, acquireTokenOptions, user); + var eventArgs = new OnBehalfOfEventArgs() { User = user }; + await options.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(builder, acquireTokenOptions, eventArgs); var result = await builder.ExecuteAsync(); From fd9fa35ee8df25c1dbebec82f5f29bab9217bab3 Mon Sep 17 00:00:00 2001 From: trwalke Date: Mon, 9 Feb 2026 22:29:04 -0800 Subject: [PATCH 3/4] Updated comments --- .../OnBehalfOfEventArgs.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/OnBehalfOfEventArgs.cs b/src/Microsoft.Identity.Web.TokenAcquisition/OnBehalfOfEventArgs.cs index 2e29e3512..6f32712fc 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/OnBehalfOfEventArgs.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/OnBehalfOfEventArgs.cs @@ -7,18 +7,20 @@ namespace Microsoft.Identity.Web { /// /// Event arguments for on-behalf-of token acquisition operations. - /// Contains context information about the user and additional data for the token request. + /// Contains user assertion token information about the user and additional data for the token request. /// public class OnBehalfOfEventArgs { /// /// Gets or sets the claims principal representing the user for whom the token is being acquired. - /// This is the claims principal into the the api + /// This is the claims principal into the the api. + /// This value can be null. /// public ClaimsPrincipal? User { get; set; } /// /// Gets or sets additional context information for the token acquisition operation. + /// If the incoming token is encrypted, it will be decrypted and made available in this property. /// public string? UserAssertionToken { get; set; } } From 37b6316951899197a8b168801ea83849b541b2c5 Mon Sep 17 00:00:00 2001 From: trwalke Date: Tue, 10 Feb 2026 13:54:37 -0800 Subject: [PATCH 4/4] Updating PR --- .../TokenAcquisition.cs | 8 ++++---- src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs | 2 +- .../AzureFunctionsAuthenticationHttpContextExtension.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs index d53718594..361b86963 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs @@ -1275,12 +1275,12 @@ private void NotifyCertificateSelection( { builder.WithSendX5C(mergedOptions.SendX5C); - ClaimsPrincipal? user = _tokenAcquisitionHost.GetUserFromRequest(); + ClaimsPrincipal? userForCcsRouting = _tokenAcquisitionHost.GetUserFromRequest(); var userTenant = string.Empty; - if (user != null) + if (userForCcsRouting != null) { - userTenant = user.GetTenantId(); - builder.WithCcsRoutingHint(user.GetObjectId(), userTenant); + userTenant = userForCcsRouting.GetTenantId(); + builder.WithCcsRoutingHint(userForCcsRouting.GetObjectId(), userTenant); } if (!string.IsNullOrEmpty(tenantId)) { diff --git a/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs b/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs index 93e392698..e259536ee 100644 --- a/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs +++ b/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs @@ -53,7 +53,7 @@ public class AuthorizeForScopesAttribute : ExceptionFilterAttribute /// /// Handles the . /// - /// UserAssertionToken provided by ASP.NET Core. + /// context provided by ASP.NET Core. public override void OnException(ExceptionContext context) { if (context != null) diff --git a/src/Microsoft.Identity.Web/AzureFunctionsAuthenticationHttpContextExtension.cs b/src/Microsoft.Identity.Web/AzureFunctionsAuthenticationHttpContextExtension.cs index 876db1328..22cba6bb1 100644 --- a/src/Microsoft.Identity.Web/AzureFunctionsAuthenticationHttpContextExtension.cs +++ b/src/Microsoft.Identity.Web/AzureFunctionsAuthenticationHttpContextExtension.cs @@ -20,7 +20,7 @@ public static class AzureFunctionsAuthenticationHttpContextExtension /// Calling this method from your Azure function validates the token and exposes the identity of the user or app on behalf of which your function is called, /// in the HttpContext.User member, where your function can make use of it. /// - /// The current HTTP UserAssertionToken, such as req.HttpContext. + /// The current HTTP Context, such as req.HttpContext. /// A task indicating success or failure. In case of failure . public static async Task<(bool, IActionResult?)> AuthenticateAzureFunctionAsync( this HttpContext httpContext)