From 58a9a4f9d99b66b5b6ea353fc7f9ca604a19583f Mon Sep 17 00:00:00 2001 From: trwalke Date: Mon, 26 Jan 2026 10:30:54 -0800 Subject: [PATCH 1/4] adding OnBeforeTokenAcquisitionForOnBehalfOf event --- .../net10.0/InternalAPI.Unshipped.txt | 1 + .../PublicAPI/net10.0/PublicAPI.Unshipped.txt | 3 ++ .../net462/InternalAPI.Unshipped.txt | 1 + .../PublicAPI/net462/PublicAPI.Unshipped.txt | 3 ++ .../net472/InternalAPI.Unshipped.txt | 1 + .../PublicAPI/net472/PublicAPI.Unshipped.txt | 3 ++ .../net8.0/InternalAPI.Unshipped.txt | 1 + .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 3 ++ .../net9.0/InternalAPI.Unshipped.txt | 1 + .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 3 ++ .../netstandard2.0/InternalAPI.Unshipped.txt | 1 + .../netstandard2.0/PublicAPI.Unshipped.txt | 3 ++ .../TokenAcquisition.cs | 8 +++ .../TokenAcquisitionExtensionOptions.cs | 19 +++++++ .../TokenAcquisitionExtensions.cs | 7 +++ .../TokenAcquisitionAddInTests.cs | 51 +++++++++++++++++++ 16 files changed, 109 insertions(+) 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 72f068746..cce4ad732 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 @@ -2,3 +2,4 @@ const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 7dc5c5811..8ed9304ac 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 +1,4 @@ #nullable enable +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 72f068746..cce4ad732 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt @@ -2,3 +2,4 @@ const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 7dc5c5811..8ed9304ac 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -1 +1,4 @@ #nullable enable +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 72f068746..cce4ad732 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt @@ -2,3 +2,4 @@ const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 7dc5c5811..8ed9304ac 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1 +1,4 @@ #nullable enable +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 72f068746..cce4ad732 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 @@ -2,3 +2,4 @@ const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 7dc5c5811..8ed9304ac 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 +1,4 @@ #nullable enable +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 72f068746..cce4ad732 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 @@ -2,3 +2,4 @@ const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 7dc5c5811..8ed9304ac 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 +1,4 @@ #nullable enable +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 72f068746..cce4ad732 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 @@ -2,3 +2,4 @@ const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void 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 7dc5c5811..8ed9304ac 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 +1,4 @@ #nullable enable +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.TokenAcquisitionExtensionOptions.OnBeforeTokenAcquisitionForOnBehalfOf -> Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf? +virtual Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf.Invoke(Microsoft.Identity.Client.AcquireTokenOnBehalfOfParameterBuilder! builder, Microsoft.Identity.Abstractions.AcquireTokenOptions? acquireTokenOptions, System.Security.Claims.ClaimsPrincipal! user) -> void diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs index 55436d560..1fe2f1607 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs @@ -1156,10 +1156,13 @@ private void NotifyCertificateSelection( string? tokenUsedToCallTheWebApi = GetActualToken(validatedToken); AcquireTokenOnBehalfOfParameterBuilder? builder = null; + TokenAcquisitionExtensionOptions? addInOptions = null; // Case of web APIs: we need to do an on-behalf-of flow, with the token used to call the API if (tokenUsedToCallTheWebApi != null) { + addInOptions = tokenAcquisitionExtensionOptionsMonitor?.CurrentValue; + if (string.IsNullOrEmpty(tokenAcquisitionOptions?.LongRunningWebApiSessionKey)) { builder = application @@ -1216,6 +1219,11 @@ private void NotifyCertificateSelection( } if (tokenAcquisitionOptions != null) { + if (addInOptions != null) + { + addInOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(builder, tokenAcquisitionOptions, user!); + } + AddFmiPathForSignedAssertionIfNeeded(tokenAcquisitionOptions, builder); var dict = MergeExtraQueryParameters(mergedOptions, tokenAcquisitionOptions); diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs index b2ef5e167..3242fcf27 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs @@ -42,6 +42,25 @@ internal void InvokeOnBeforeTokenAcquisitionForApp(AcquireTokenForClientParamete /// public event BeforeTokenAcquisitionForTestUserAsync? OnBeforeTokenAcquisitionForTestUserAsync; + /// + /// Occurs before an asynchronous token acquisition operation for the On-Behalf-Of authentication flow is + /// initiated. + /// + public event BeforeTokenAcquisitionForOnBehalfOf? OnBeforeTokenAcquisitionForOnBehalfOf; + + /// + /// Invoke the OnBeforeTokenAcquisitionForApp event. + /// + internal void InvokeOnBeforeTokenAcquisitionForOnBehalfOf(AcquireTokenOnBehalfOfParameterBuilder builder, + AcquireTokenOptions? acquireTokenOptions, + ClaimsPrincipal user) + { + if (OnBeforeTokenAcquisitionForOnBehalfOf != null) + { + OnBeforeTokenAcquisitionForOnBehalfOf(builder, acquireTokenOptions, user); + } + } + /// /// Invoke the BeforeTokenAcquisitionForTestUser event. /// diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs index c2394f670..5ab50b868 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs @@ -31,4 +31,11 @@ namespace Microsoft.Identity.Web /// User claims. 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). + /// + /// Builder + /// Token acquisition options for the request. Can be null. + /// User claims. + public delegate void BeforeTokenAcquisitionForOnBehalfOf(AcquireTokenOnBehalfOfParameterBuilder builder, AcquireTokenOptions? acquireTokenOptions, ClaimsPrincipal user); } diff --git a/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs b/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs index 625d83ac8..7850cfdb6 100644 --- a/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs +++ b/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs @@ -121,5 +121,56 @@ public async Task InvokeOnBeforeTokenAcquisitionForUsernamePassword_InvokesEvent Assert.NotNull(result); Assert.Equal(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); } + + [Fact] + public async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOf_InvokesEvent() + { + // Arrange + var options = new TokenAcquisitionExtensionOptions(); + var acquireTokenOptions = new AcquireTokenOptions(); + acquireTokenOptions.ForceRefresh = true; + + //Configure mocks + using MockHttpClientFactory mockHttpClient = new(); + mockHttpClient.AddMockHandler(MockHttpCreator.CreateClientCredentialTokenHandler()); + + var confidentialApp = ConfidentialClientApplicationBuilder + .Create(TestConstants.ClientId) + .WithAuthority(TestConstants.AuthorityCommonTenant) + .WithHttpClientFactory(mockHttpClient) + .WithInstanceDiscovery(false) + .WithClientSecret(TestConstants.ClientSecret) + .Build(); + + var userAssertion = new UserAssertion("user-assertion-token"); + AcquireTokenOnBehalfOfParameterBuilder builder = confidentialApp + .AcquireTokenOnBehalfOf(new string[] { "scope" }, userAssertion); + + bool eventInvoked = false; + options.OnBeforeTokenAcquisitionForOnBehalfOf += (builder, options, user) => + { + eventInvoked = true; + + //Set ForceRefresh on the builder + builder.WithForceRefresh(options!.ForceRefresh); + }; + + var user = new ClaimsPrincipal( + new CaseSensitiveClaimsIdentity(new[] + { + new Claim(ClaimConstants.Sub, "user-id"), + new Claim(ClaimConstants.Name, "Test User"), + })); + + // Act + options.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(builder, acquireTokenOptions, user); + + var result = await builder.ExecuteAsync(); + + // Assert + Assert.True(eventInvoked); + Assert.NotNull(result); + Assert.Equal(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); + } } } From 6903b61d0c9385dc70e85956c57b1dc09ec73d2a Mon Sep 17 00:00:00 2001 From: trwalke Date: Mon, 26 Jan 2026 23:14:33 -0800 Subject: [PATCH 2/4] Adding async event --- Directory.Build.props | 2 +- ...osoft.Identity.Web.TokenAcquisition.csproj | 1 + .../net10.0/InternalAPI.Unshipped.txt | 3 +- .../PublicAPI/net10.0/PublicAPI.Unshipped.txt | 3 ++ .../net462/InternalAPI.Unshipped.txt | 3 +- .../PublicAPI/net462/PublicAPI.Unshipped.txt | 3 ++ .../net472/InternalAPI.Unshipped.txt | 3 +- .../PublicAPI/net472/PublicAPI.Unshipped.txt | 3 ++ .../net8.0/InternalAPI.Unshipped.txt | 3 +- .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 3 ++ .../net9.0/InternalAPI.Unshipped.txt | 3 +- .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 3 ++ .../netstandard2.0/InternalAPI.Unshipped.txt | 3 +- .../netstandard2.0/PublicAPI.Unshipped.txt | 3 ++ .../TokenAcquisition.cs | 2 +- .../TokenAcquisitionExtensionOptions.cs | 30 +++++++++++++++++++ .../TokenAcquisitionExtensions.cs | 8 +++++ .../TokenAcquisitionAddInTests.cs | 15 +++++++--- 18 files changed, 82 insertions(+), 12 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 8a02762f5..c9d77a1d6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 4.3.0 + 4.3.1-preview $(MicrosoftIdentityWebVersion) diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/Microsoft.Identity.Web.TokenAcquisition.csproj b/src/Microsoft.Identity.Web.TokenAcquisition/Microsoft.Identity.Web.TokenAcquisition.csproj index 34322a4d9..94f899947 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/Microsoft.Identity.Web.TokenAcquisition.csproj +++ b/src/Microsoft.Identity.Web.TokenAcquisition/Microsoft.Identity.Web.TokenAcquisition.csproj @@ -6,6 +6,7 @@ {74737C0A-25E6-4E2C-B3AA-F7EECB7A07C7} true README.md + True 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 cce4ad732..47e6d8b58 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,5 +1,6 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! 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 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 8ed9304ac..9833e6abf 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,4 +1,7 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync 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! 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 cce4ad732..47e6d8b58 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt @@ -1,5 +1,6 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! 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 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 8ed9304ac..9833e6abf 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -1,4 +1,7 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync 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! 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 cce4ad732..47e6d8b58 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt @@ -1,5 +1,6 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! 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 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 8ed9304ac..9833e6abf 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,4 +1,7 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync 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! 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 cce4ad732..47e6d8b58 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,5 +1,6 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! 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 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 8ed9304ac..9833e6abf 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,4 +1,7 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync 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! 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 cce4ad732..47e6d8b58 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,5 +1,6 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! 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 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 8ed9304ac..9833e6abf 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,4 +1,7 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync 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! 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 cce4ad732..47e6d8b58 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,5 +1,6 @@ #nullable enable const Microsoft.Identity.Web.Constants.ClientAssertionContainsInvalidSignature = "AADSTS7000274" -> string! const Microsoft.Identity.Web.Constants.CertificateWasRevoked = "AADSTS7000277" -> string! -static readonly Microsoft.Identity.Web.Constants.s_certificateRelatedErrorCodes -> System.Collections.Generic.HashSet! 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 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 8ed9304ac..9833e6abf 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,4 +1,7 @@ #nullable enable Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOf +Microsoft.Identity.Web.BeforeTokenAcquisitionForOnBehalfOfAsync 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! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs index 1fe2f1607..941ecbe50 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs @@ -1221,7 +1221,7 @@ private void NotifyCertificateSelection( { if (addInOptions != null) { - addInOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(builder, tokenAcquisitionOptions, user!); + await addInOptions.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(builder, tokenAcquisitionOptions, user!).ConfigureAwait(false); } AddFmiPathForSignedAssertionIfNeeded(tokenAcquisitionOptions, builder); diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs index 3242fcf27..a7bafc8cd 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs @@ -48,6 +48,12 @@ internal void InvokeOnBeforeTokenAcquisitionForApp(AcquireTokenForClientParamete /// public event BeforeTokenAcquisitionForOnBehalfOf? OnBeforeTokenAcquisitionForOnBehalfOf; + /// + /// Occurs before an asynchronous token acquisition operation for the On-Behalf-Of authentication flow is + /// initiated. + /// + public event BeforeTokenAcquisitionForOnBehalfOfAsync? OnBeforeTokenAcquisitionForOnBehalfOfAsync; + /// /// Invoke the OnBeforeTokenAcquisitionForApp event. /// @@ -61,6 +67,30 @@ internal void InvokeOnBeforeTokenAcquisitionForOnBehalfOf(AcquireTokenOnBehalfOf } } + /// + /// Invoke the OnBeforeTokenAcquisitionForApp event. + /// + internal async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(AcquireTokenOnBehalfOfParameterBuilder builder, + AcquireTokenOptions? acquireTokenOptions, + ClaimsPrincipal user) + { + // 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, + // nor do they support awaiting natively + var invocationList = OnBeforeTokenAcquisitionForOnBehalfOfAsync.GetInvocationList(); + var tasks = invocationList + .Cast() + .Select(handler => handler(builder, acquireTokenOptions, user)); + await Task.WhenAll(tasks); + } + + // Run the sync event if it is not null. + OnBeforeTokenAcquisitionForOnBehalfOf?.Invoke(builder, acquireTokenOptions, user); + } + /// /// Invoke the BeforeTokenAcquisitionForTestUser event. /// diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs index 5ab50b868..28035d901 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensions.cs @@ -38,4 +38,12 @@ namespace Microsoft.Identity.Web /// Token acquisition options for the request. Can be null. /// User claims. public delegate void BeforeTokenAcquisitionForOnBehalfOf(AcquireTokenOnBehalfOfParameterBuilder builder, AcquireTokenOptions? acquireTokenOptions, ClaimsPrincipal user); + + /// + /// 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); } diff --git a/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs b/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs index 7850cfdb6..6ef66014a 100644 --- a/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs +++ b/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs @@ -147,12 +147,19 @@ public async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOf_InvokesEvent() .AcquireTokenOnBehalfOf(new string[] { "scope" }, userAssertion); bool eventInvoked = false; + MsalAuthenticationExtension extension = new MsalAuthenticationExtension(); options.OnBeforeTokenAcquisitionForOnBehalfOf += (builder, options, user) => { - eventInvoked = true; + MsalAuthenticationExtension extension = new MsalAuthenticationExtension(); - //Set ForceRefresh on the builder - builder.WithForceRefresh(options!.ForceRefresh); + extension.OnBeforeTokenRequestHandler = (request) => + { + eventInvoked = true; + request.BodyParameters.Add("x-ms-user", user.FindFirst("user")?.Value); + return Task.CompletedTask; + }; + + builder.WithAuthenticationExtension(extension); }; var user = new ClaimsPrincipal( @@ -163,7 +170,7 @@ public async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOf_InvokesEvent() })); // Act - options.InvokeOnBeforeTokenAcquisitionForOnBehalfOf(builder, acquireTokenOptions, user); + await options.InvokeOnBeforeTokenAcquisitionForOnBehalfOfAsync(builder, acquireTokenOptions, user); var result = await builder.ExecuteAsync(); From 0419c2f4bcdc7956fcc4d13e78f3f13a215e932c Mon Sep 17 00:00:00 2001 From: trwalke Date: Tue, 27 Jan 2026 08:49:00 -0800 Subject: [PATCH 3/4] Update --- .../TokenAcquisitionExtensionOptions.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs index a7bafc8cd..0d0ca0cb4 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisitionExtensionOptions.cs @@ -54,19 +54,6 @@ internal void InvokeOnBeforeTokenAcquisitionForApp(AcquireTokenForClientParamete /// public event BeforeTokenAcquisitionForOnBehalfOfAsync? OnBeforeTokenAcquisitionForOnBehalfOfAsync; - /// - /// Invoke the OnBeforeTokenAcquisitionForApp event. - /// - internal void InvokeOnBeforeTokenAcquisitionForOnBehalfOf(AcquireTokenOnBehalfOfParameterBuilder builder, - AcquireTokenOptions? acquireTokenOptions, - ClaimsPrincipal user) - { - if (OnBeforeTokenAcquisitionForOnBehalfOf != null) - { - OnBeforeTokenAcquisitionForOnBehalfOf(builder, acquireTokenOptions, user); - } - } - /// /// Invoke the OnBeforeTokenAcquisitionForApp event. /// From 58097b3180d402e8eddadddd03fa9311795b4396 Mon Sep 17 00:00:00 2001 From: trwalke Date: Wed, 28 Jan 2026 10:41:16 -0800 Subject: [PATCH 4/4] Adding additional test case --- .../TokenAcquisitionAddInTests.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs b/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs index 6ef66014a..2148e03ce 100644 --- a/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs +++ b/tests/Microsoft.Identity.Web.Test/TokenAcquisitionAddInTests.cs @@ -12,6 +12,9 @@ using System.Collections.Generic; using Microsoft.IdentityModel.Tokens; using System.Security.Claims; +using Microsoft.Identity.Client.AuthScheme; +using System.Threading; +using System; namespace Microsoft.Identity.Web.Tests { @@ -140,6 +143,7 @@ public async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOf_InvokesEvent() .WithHttpClientFactory(mockHttpClient) .WithInstanceDiscovery(false) .WithClientSecret(TestConstants.ClientSecret) + .WithExperimentalFeatures(true) .Build(); var userAssertion = new UserAssertion("user-assertion-token"); @@ -147,11 +151,23 @@ public async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOf_InvokesEvent() .AcquireTokenOnBehalfOf(new string[] { "scope" }, userAssertion); bool eventInvoked = false; + bool formatResultInvoked = false; + MsalAuthenticationExtension extension = new MsalAuthenticationExtension(); options.OnBeforeTokenAcquisitionForOnBehalfOf += (builder, options, user) => { MsalAuthenticationExtension extension = new MsalAuthenticationExtension(); + // Create a test authentication operation implementing IAuthenticationOperation2 + var authOperation = new TestAuthenticationOperation2 + { + OnFormatResult = (result) => + { + formatResultInvoked = true; + return Task.FromResult(result); + } + }; + extension.AuthenticationOperation = authOperation; extension.OnBeforeTokenRequestHandler = (request) => { eventInvoked = true; @@ -176,8 +192,38 @@ public async Task InvokeOnBeforeTokenAcquisitionForOnBehalfOf_InvokesEvent() // Assert Assert.True(eventInvoked); + Assert.True(formatResultInvoked); Assert.NotNull(result); Assert.Equal(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); } + + // Helper class for testing IAuthenticationOperation2 + private class TestAuthenticationOperation2 : IAuthenticationOperation2 + { + public Func>? OnFormatResult { get; set; } + + public int TelemetryTokenType => 0; + + public string AuthorizationHeaderPrefix => "Bearer"; + + public string KeyId => string.Empty; + + public string AccessTokenType => "Bearer"; + + public void FormatResult(AuthenticationResult authenticationResult) { } + + public Task FormatResultAsync(AuthenticationResult authenticationResult, CancellationToken cancellationToken = default) + { + if (OnFormatResult != null) + { + return OnFormatResult(authenticationResult); + } + return Task.FromResult(authenticationResult); + } + + public IReadOnlyDictionary GetTokenRequestParams() => new Dictionary(); + + public Task ValidateCachedTokenAsync(MsalCacheValidationData cachedTokenData) => Task.FromResult(false); + } } }