From 3e6d41c89afdc4b6dbcd5b96995b1e9b55456fda Mon Sep 17 00:00:00 2001 From: Jennyf19 Date: Fri, 18 Sep 2020 07:27:58 -0700 Subject: [PATCH 1/8] add token acquisition options for extensibility w/msal --- .../DownstreamWebApi.cs | 9 +- .../DownstreamWebApiOptions.cs | 6 + .../ITokenAcquisition.cs | 14 ++- .../Microsoft.Identity.Web.xml | 50 ++++++-- .../TokenAcquisition.cs | 109 ++++++++++++------ .../TokenAcquisitionOptions.cs | 38 ++++++ .../Controllers/WeatherForecastController.cs | 6 +- .../TestConstants.cs | 17 +++ .../AcquireTokenForUserIntegrationTests.cs | 1 + .../WebAppExtensionsTests.cs | 2 +- 10 files changed, 199 insertions(+), 53 deletions(-) create mode 100644 src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs diff --git a/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApi.cs b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApi.cs index 9cced67c6..e3f2d3b25 100644 --- a/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApi.cs +++ b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApi.cs @@ -3,13 +3,11 @@ using System; using System.Globalization; -using System.Net; using System.Net.Http; using System.Security.Claims; using System.Text; using System.Text.Json; using System.Threading.Tasks; -using Microsoft.Extensions.Azure; using Microsoft.Extensions.Options; namespace Microsoft.Identity.Web @@ -76,7 +74,9 @@ public async Task CallWebApiForUserAsync( string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync( effectiveOptions.GetScopes(), effectiveOptions.Tenant, - userflow) + userflow, + user, + effectiveOptions.TokenAcquisitionOptions) .ConfigureAwait(false); HttpResponseMessage response; @@ -177,7 +177,8 @@ public async Task CallWebApiForAppAsync( string accessToken = await _tokenAcquisition.GetAccessTokenForAppAsync( effectiveOptions.Scopes, - effectiveOptions.Tenant) + effectiveOptions.Tenant, + effectiveOptions.TokenAcquisitionOptions) .ConfigureAwait(false); HttpResponseMessage response; diff --git a/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs index dec4da9d7..53fdc029b 100644 --- a/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs +++ b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs @@ -46,6 +46,11 @@ public class DownstreamWebApiOptions /// public HttpMethod HttpMethod { get; set; } = HttpMethod.Get; + /// + /// todo. + /// + public TokenAcquisitionOptions TokenAcquisitionOptions { get; set; } = new TokenAcquisitionOptions(); + /// /// Clone the options (to be able to override them). /// @@ -60,6 +65,7 @@ public DownstreamWebApiOptions Clone() Tenant = Tenant, UserFlow = UserFlow, HttpMethod = HttpMethod, + TokenAcquisitionOptions = TokenAcquisitionOptions.Clone(), }; } diff --git a/src/Microsoft.Identity.Web/ITokenAcquisition.cs b/src/Microsoft.Identity.Web/ITokenAcquisition.cs index bed44fed1..9b540f674 100644 --- a/src/Microsoft.Identity.Web/ITokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/ITokenAcquisition.cs @@ -26,12 +26,14 @@ public interface ITokenAcquisition /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. + /// /// An access token to call on behalf of the user, the downstream API characterized by its scopes. Task GetAccessTokenForUserAsync( IEnumerable scopes, string? tenantId = null, string? userFlow = null, - ClaimsPrincipal? user = null); + ClaimsPrincipal? user = null, + TokenAcquisitionOptions? tokenAcquisitionOptions = null); /// /// Typically used from an ASP.NET Core web app or web API controller, this method gets an access token @@ -45,12 +47,14 @@ Task GetAccessTokenForUserAsync( /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. + /// /// An to call on behalf of the user, the downstream API characterized by its scopes. Task GetAuthenticationResultForUserAsync( IEnumerable scopes, string? tenantId = null, string? userFlow = null, - ClaimsPrincipal? user = null); + ClaimsPrincipal? user = null, + TokenAcquisitionOptions? tokenAcquisitionOptions = null); /// /// Acquires a token from the authority configured in the app, for the confidential client itself (not on behalf of a user) @@ -63,8 +67,12 @@ Task GetAuthenticationResultForUserAsync( /// several calls to get tokens for other resources). /// Enables overriding of the tenant/account for the same identity. This is useful in the /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. + /// /// An access token for the app itself, based on its scopes. - Task GetAccessTokenForAppAsync(string scope, string? tenant = null); + Task GetAccessTokenForAppAsync( + string scope, + string? tenant = null, + TokenAcquisitionOptions? tokenAcquisitionOptions = null); /// /// Used in web APIs (which therefore cannot have an interaction with the user). diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 6a38db326..5d3a93300 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -667,6 +667,11 @@ HTTP method used to call this downstream web API (by default Get). + + + todo. + + Clone the options (to be able to override them). @@ -884,7 +889,7 @@ Interface for the token acquisition service (encapsulating MSAL.NET). - + Typically used from an ASP.NET Core web app or web API controller, this method gets an access token for a downstream API on behalf of the user account which claims are provided in the @@ -897,9 +902,10 @@ Optional claims principal representing the user. If not provided, will use the signed-in user (in a web app), or the user for which the token was received (in a web API) cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. + An access token to call on behalf of the user, the downstream API characterized by its scopes. - + Typically used from an ASP.NET Core web app or web API controller, this method gets an access token for a downstream API on behalf of the user account which claims are provided in the @@ -912,9 +918,10 @@ Optional claims principal representing the user. If not provided, will use the signed-in user (in a web app), or the user for which the token was received (in a web API) cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. + An to call on behalf of the user, the downstream API characterized by its scopes. - + Acquires a token from the authority configured in the app, for the confidential client itself (not on behalf of a user) using the client credentials flow. See https://aka.ms/msal-net-client-credentials. @@ -926,6 +933,7 @@ several calls to get tokens for other resources). Enables overriding of the tenant/account for the same identity. This is useful in the cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. + An access token for the app itself, based on its scopes. @@ -1458,7 +1466,7 @@ - + Typically used from a web app or web API controller, this method retrieves an access token for a downstream API using; @@ -1474,6 +1482,7 @@ Optional claims principal representing the user. If not provided, will use the signed-in user (in a web app), or the user for which the token was received (in a web API) cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. + An access token to call the downstream API and populated with this downstream API's scopes. Calling this method from a web API supposes that you have previously called, in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method @@ -1481,7 +1490,7 @@ you have previously called AddAccountToCacheFromAuthorizationCodeAsync from a method called by OpenIdConnectOptions.Events.OnAuthorizationCodeReceived. - + Acquires a token from the authority configured in the app, for the confidential client itself (not on behalf of a user) using the client credentials flow. See https://aka.ms/msal-net-client-credentials. @@ -1493,9 +1502,10 @@ several calls to get tokens for other resources). Enables overriding of the tenant/account for the same identity. This is useful for multi tenant apps or daemons. + An access token for the app itself, based on its scopes. - + Typically used from a web app or web API controller, this method retrieves an access token for a downstream API using; @@ -1511,6 +1521,7 @@ Optional claims principal representing the user. If not provided, will use the signed-in user (in a web app), or the user for which the token was received (in a web API) cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. + An access token to call the downstream API and populated with this downstream API's scopes. Calling this method from a web API supposes that you have previously called, in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method @@ -1547,7 +1558,7 @@ Creates an MSAL confidential client application. - + Gets an access token for a downstream API on behalf of the user described by its claimsPrincipal. @@ -1558,7 +1569,7 @@ on behalf of the user described in the claimsPrincipal. Azure AD B2C user flow to target. - + Gets an access token for a downstream API on behalf of the user whose account is passed as an argument. @@ -1569,6 +1580,29 @@ Authority based on a specific tenant for which to acquire a token to access the scopes on behalf of the user. Azure AD B2C user flow. + + + + + Options passed-in to create the token acquisition object with calls into MSAL .NET. + + + + + Sets the correlation id to be used in the authentication request + to the /token endpoint. + + + + + Sets Extra Query Parameters for the query string in the HTTP authentication request. + + + + + Clone the options (to be able to override them). + + A clone of the options. diff --git a/src/Microsoft.Identity.Web/TokenAcquisition.cs b/src/Microsoft.Identity.Web/TokenAcquisition.cs index 70e967dfb..d0b630e00 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisition.cs @@ -31,7 +31,6 @@ internal class TokenAcquisition : ITokenAcquisition, ITokenAcquisitionInternal { private readonly MicrosoftIdentityOptions _microsoftIdentityOptions; private readonly ConfidentialClientApplicationOptions _applicationOptions; - private readonly IMsalTokenCacheProvider _tokenCacheProvider; private IConfidentialClientApplication? _application; @@ -185,6 +184,7 @@ public async Task AddAccountToCacheFromAuthorizationCodeAsync( /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. + /// /// An access token to call the downstream API and populated with this downstream API's scopes. /// Calling this method from a web API supposes that you have previously called, /// in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method @@ -195,7 +195,8 @@ public async Task GetAuthenticationResultForUserAsync( IEnumerable scopes, string? tenant = null, string? userFlow = null, - ClaimsPrincipal? user = null) + ClaimsPrincipal? user = null, + TokenAcquisitionOptions? tokenAcquisitionOptions = null) { if (scopes == null) { @@ -214,7 +215,8 @@ public async Task GetAuthenticationResultForUserAsync( authenticationResult = await GetAuthenticationResultForWebApiToCallDownstreamApiAsync( _application, authority, - scopes).ConfigureAwait(false); + scopes, + tokenAcquisitionOptions).ConfigureAwait(false); if (authenticationResult != null) { @@ -252,8 +254,12 @@ public async Task GetAuthenticationResultForUserAsync( /// several calls to get tokens for other resources). /// Enables overriding of the tenant/account for the same identity. This is useful /// for multi tenant apps or daemons. + /// /// An access token for the app itself, based on its scopes. - public async Task GetAccessTokenForAppAsync(string scope, string? tenant = null) + public async Task GetAccessTokenForAppAsync( + string scope, + string? tenant = null, + TokenAcquisitionOptions? tokenAcquisitionOptions = null) { if (string.IsNullOrEmpty(scope)) { @@ -275,12 +281,19 @@ public async Task GetAccessTokenForAppAsync(string scope, string? tenant string authority = CreateAuthorityBasedOnTenantIfProvided(_application, tenant); AuthenticationResult result; - result = await _application + var builder = _application .AcquireTokenForClient(new string[] { scope }.Except(_scopesRequestedByMsal)) .WithSendX5C(_microsoftIdentityOptions.SendX5C) - .WithAuthority(authority) - .ExecuteAsync() - .ConfigureAwait(false); + .WithAuthority(authority); + + if (tokenAcquisitionOptions != null) + { + builder.WithExtraQueryParameters(tokenAcquisitionOptions.ExtraQueryParameters); + builder.WithCorrelationId(tokenAcquisitionOptions.CorrelationId); + } + + result = await builder.ExecuteAsync() + .ConfigureAwait(false); return result.AccessToken; } @@ -300,6 +313,7 @@ public async Task GetAccessTokenForAppAsync(string scope, string? tenant /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. + /// /// An access token to call the downstream API and populated with this downstream API's scopes. /// Calling this method from a web API supposes that you have previously called, /// in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method @@ -310,9 +324,16 @@ public async Task GetAccessTokenForUserAsync( IEnumerable scopes, string? tenant = null, string? userFlow = null, - ClaimsPrincipal? user = null) + ClaimsPrincipal? user = null, + TokenAcquisitionOptions? tokenAcquisitionOptions = null) { - AuthenticationResult result = await GetAuthenticationResultForUserAsync(scopes, tenant, userFlow, user).ConfigureAwait(false); + AuthenticationResult result = + await GetAuthenticationResultForUserAsync( + scopes, + tenant, + userFlow, + user, + tokenAcquisitionOptions).ConfigureAwait(false); return result.AccessToken; } @@ -492,7 +513,8 @@ private async Task BuildConfidentialClientApplic private async Task GetAuthenticationResultForWebApiToCallDownstreamApiAsync( IConfidentialClientApplication application, string authority, - IEnumerable scopes) + IEnumerable scopes, + TokenAcquisitionOptions? tokenAcquisitionOptions) { try { @@ -505,13 +527,21 @@ private async Task BuildConfidentialClientApplic // In the case the token is a JWE (encrypted token), we use the decrypted token. string tokenUsedToCallTheWebApi = validatedToken.InnerToken == null ? validatedToken.RawData : validatedToken.InnerToken.RawData; - var result = await application - .AcquireTokenOnBehalfOf(scopes.Except(_scopesRequestedByMsal), new UserAssertion(tokenUsedToCallTheWebApi)) + var builder = application + .AcquireTokenOnBehalfOf( + scopes.Except(_scopesRequestedByMsal), + new UserAssertion(tokenUsedToCallTheWebApi)) .WithSendX5C(_microsoftIdentityOptions.SendX5C) - .WithAuthority(authority) - .ExecuteAsync() - .ConfigureAwait(false); - return result; + .WithAuthority(authority); + + if (tokenAcquisitionOptions != null) + { + builder.WithExtraQueryParameters(tokenAcquisitionOptions.ExtraQueryParameters); + builder.WithCorrelationId(tokenAcquisitionOptions.CorrelationId); + } + + return await builder.ExecuteAsync() + .ConfigureAwait(false); } return null; @@ -537,7 +567,8 @@ private async Task GetAuthenticationResultForWebAppWithAcc ClaimsPrincipal? claimsPrincipal, IEnumerable scopes, string? authority, - string? userFlow = null) + string? userFlow = null, + TokenAcquisitionOptions? tokenAcquisitionOptions = null) { IAccount? account = null; if (_microsoftIdentityOptions.IsB2C && !string.IsNullOrEmpty(userFlow)) @@ -561,7 +592,9 @@ private async Task GetAuthenticationResultForWebAppWithAcc application, account, scopes, - authority).ConfigureAwait(false); + authority, + userFlow, + tokenAcquisitionOptions).ConfigureAwait(false); } /// @@ -574,19 +607,30 @@ private async Task GetAuthenticationResultForWebAppWithAcc /// Authority based on a specific tenant for which to acquire a token to access the scopes /// on behalf of the user. /// Azure AD B2C user flow. + /// private async Task GetAuthenticationResultForWebAppWithAccountFromCacheAsync( IConfidentialClientApplication application, IAccount? account, IEnumerable scopes, string? authority, - string? userFlow = null) + string? userFlow = null, + TokenAcquisitionOptions? tokenAcquisitionOptions = null) { if (scopes == null) { throw new ArgumentNullException(nameof(scopes)); } - AuthenticationResult result; + var builder = application + .AcquireTokenSilent(scopes.Except(_scopesRequestedByMsal), account) + .WithSendX5C(_microsoftIdentityOptions.SendX5C); + + if (tokenAcquisitionOptions != null) + { + builder.WithExtraQueryParameters(tokenAcquisitionOptions.ExtraQueryParameters); + builder.WithCorrelationId(tokenAcquisitionOptions.CorrelationId); + } + // Acquire an access token as a B2C authority if (_microsoftIdentityOptions.IsB2C) { @@ -594,23 +638,16 @@ private async Task GetAuthenticationResultForWebAppWithAcc new Uri(application.Authority).PathAndQuery, $"/{ClaimConstants.Tfp}/{_microsoftIdentityOptions.Domain}/{userFlow ?? _microsoftIdentityOptions.DefaultUserFlow}"); - result = await application - .AcquireTokenSilent(scopes.Except(_scopesRequestedByMsal), account) - .WithB2CAuthority(b2cAuthority) - .WithSendX5C(_microsoftIdentityOptions.SendX5C) - .ExecuteAsync() - .ConfigureAwait(false); - - return result; + builder.WithB2CAuthority(b2cAuthority) + .WithSendX5C(_microsoftIdentityOptions.SendX5C); + } + else + { + builder.WithAuthority(authority); } - result = await application - .AcquireTokenSilent(scopes.Except(_scopesRequestedByMsal), account) - .WithAuthority(authority) - .WithSendX5C(_microsoftIdentityOptions.SendX5C) - .ExecuteAsync() - .ConfigureAwait(false); - return result; + return await builder.ExecuteAsync() + .ConfigureAwait(false); } private static bool AcceptedTokenVersionMismatch(MsalUiRequiredException msalServiceException) diff --git a/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs b/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs new file mode 100644 index 000000000..1dfee0358 --- /dev/null +++ b/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Identity.Web +{ + /// + /// Options passed-in to create the token acquisition object with calls into MSAL .NET. + /// + public class TokenAcquisitionOptions + { + /// + /// Sets the correlation id to be used in the authentication request + /// to the /token endpoint. + /// + public Guid CorrelationId { get; set; } + + /// + /// Sets Extra Query Parameters for the query string in the HTTP authentication request. + /// + public Dictionary? ExtraQueryParameters { get; set; } = null; + + /// + /// Clone the options (to be able to override them). + /// + /// A clone of the options. + public TokenAcquisitionOptions Clone() + { + return new TokenAcquisitionOptions + { + CorrelationId = CorrelationId, + ExtraQueryParameters = ExtraQueryParameters, + }; + } + } +} diff --git a/tests/IntegrationTests/IntegrationTestService/Controllers/WeatherForecastController.cs b/tests/IntegrationTests/IntegrationTestService/Controllers/WeatherForecastController.cs index a9a524322..d1a154e13 100644 --- a/tests/IntegrationTests/IntegrationTestService/Controllers/WeatherForecastController.cs +++ b/tests/IntegrationTests/IntegrationTestService/Controllers/WeatherForecastController.cs @@ -54,7 +54,11 @@ public async Task CallDownstreamWebApiGenericAsync() var user = await _downstreamWebApi.CallWebApiForUserAsync( TestConstants.SectionNameCalledApi, null, - options => { options.RelativePath = "me"; }); + options => { + options.RelativePath = "me"; + options.TokenAcquisitionOptions.CorrelationId = TestConstants.s_correlationId; + options.TokenAcquisitionOptions.ExtraQueryParameters = TestConstants.ExtraQueryParameters; + }); return user.DisplayName; } diff --git a/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs b/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs index c7c5c0109..78bf3695b 100644 --- a/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs +++ b/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.Collections.Generic; namespace Microsoft.Identity.Web.Test.Common @@ -137,5 +138,21 @@ public static class TestConstants public const string StaySignedInNoId = "idBtn_Back"; public const string PhotoLabel = "photo"; public const string Headless = "headless"; + + // TokenAcqusitionOptions + public static Dictionary ExtraQueryParameters + { + get + { + return new Dictionary() + { + { "extra", "qp" }, + { "key1", "value1%20with%20encoded%20space" }, + { "key2", "value2" }, + }; + } + } + + public static Guid s_correlationId = new Guid("6347d33d-941a-4c35-9912-a9cf54fb1b3e"); } } diff --git a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs index 66986c808..83eb45de3 100644 --- a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs +++ b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs @@ -85,6 +85,7 @@ public async Task GetTokenForUserAsync( // Assert Assert.True(response.IsSuccessStatusCode); + Assert.Equal(TestConstants.s_correlationId, result.CorrelationId); } private static async Task AcquireTokenForLabUserAsync() diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index 028add15b..bd29eaf06 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -481,7 +481,7 @@ public void AddDownstreamWebApiOptionsTest(bool useDownstreamWebApiOptions) // Assert properties set var downstreamWebApiOptions = provider.GetRequiredService>(); - IDownstreamWebApi downstreamWebApi = provider.GetRequiredService(); + provider.GetRequiredService(); if (useDownstreamWebApiOptions) { From 5ac4562253ebe9d21e42182d71c3efe3015e6d4e Mon Sep 17 00:00:00 2001 From: Jennyf19 Date: Fri, 18 Sep 2020 12:02:03 -0700 Subject: [PATCH 2/8] add xml comments --- .../DownstreamWebApiSupport/DownstreamWebApiOptions.cs | 2 +- src/Microsoft.Identity.Web/ITokenAcquisition.cs | 6 +++--- src/Microsoft.Identity.Web/TokenAcquisition.cs | 9 +++++---- src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs index 53fdc029b..e6dbcc9ed 100644 --- a/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs +++ b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs @@ -47,7 +47,7 @@ public class DownstreamWebApiOptions public HttpMethod HttpMethod { get; set; } = HttpMethod.Get; /// - /// todo. + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. /// public TokenAcquisitionOptions TokenAcquisitionOptions { get; set; } = new TokenAcquisitionOptions(); diff --git a/src/Microsoft.Identity.Web/ITokenAcquisition.cs b/src/Microsoft.Identity.Web/ITokenAcquisition.cs index 9b540f674..b801e24ea 100644 --- a/src/Microsoft.Identity.Web/ITokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/ITokenAcquisition.cs @@ -26,7 +26,7 @@ public interface ITokenAcquisition /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. - /// + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. /// An access token to call on behalf of the user, the downstream API characterized by its scopes. Task GetAccessTokenForUserAsync( IEnumerable scopes, @@ -47,7 +47,7 @@ Task GetAccessTokenForUserAsync( /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. - /// + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. /// An to call on behalf of the user, the downstream API characterized by its scopes. Task GetAuthenticationResultForUserAsync( IEnumerable scopes, @@ -67,7 +67,7 @@ Task GetAuthenticationResultForUserAsync( /// several calls to get tokens for other resources). /// Enables overriding of the tenant/account for the same identity. This is useful in the /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. - /// + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. /// An access token for the app itself, based on its scopes. Task GetAccessTokenForAppAsync( string scope, diff --git a/src/Microsoft.Identity.Web/TokenAcquisition.cs b/src/Microsoft.Identity.Web/TokenAcquisition.cs index d0b630e00..13a22d36c 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisition.cs @@ -184,7 +184,7 @@ public async Task AddAccountToCacheFromAuthorizationCodeAsync( /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. - /// + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. /// An access token to call the downstream API and populated with this downstream API's scopes. /// Calling this method from a web API supposes that you have previously called, /// in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method @@ -254,7 +254,7 @@ public async Task GetAuthenticationResultForUserAsync( /// several calls to get tokens for other resources). /// Enables overriding of the tenant/account for the same identity. This is useful /// for multi tenant apps or daemons. - /// + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. /// An access token for the app itself, based on its scopes. public async Task GetAccessTokenForAppAsync( string scope, @@ -313,7 +313,7 @@ public async Task GetAccessTokenForAppAsync( /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. - /// + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. /// An access token to call the downstream API and populated with this downstream API's scopes. /// Calling this method from a web API supposes that you have previously called, /// in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method @@ -562,6 +562,7 @@ private async Task BuildConfidentialClientApplic /// (optional) Authority based on a specific tenant for which to acquire a token to access the scopes /// on behalf of the user described in the claimsPrincipal. /// Azure AD B2C user flow to target. + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. private async Task GetAuthenticationResultForWebAppWithAccountFromCacheAsync( IConfidentialClientApplication application, ClaimsPrincipal? claimsPrincipal, @@ -607,7 +608,7 @@ private async Task GetAuthenticationResultForWebAppWithAcc /// Authority based on a specific tenant for which to acquire a token to access the scopes /// on behalf of the user. /// Azure AD B2C user flow. - /// + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. private async Task GetAuthenticationResultForWebAppWithAccountFromCacheAsync( IConfidentialClientApplication application, IAccount? account, diff --git a/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs b/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs index 1dfee0358..ec7b09ef3 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs @@ -7,7 +7,7 @@ namespace Microsoft.Identity.Web { /// - /// Options passed-in to create the token acquisition object with calls into MSAL .NET. + /// Options passed-in to create the token acquisition object which calls into MSAL .NET. /// public class TokenAcquisitionOptions { From cc6a3d8024f0b1413013a9702d6c052ad6b54ae3 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 21 Sep 2020 08:46:59 -0700 Subject: [PATCH 3/8] add force refresh logic --- .../Microsoft.Identity.Web.xml | 19 ++++++++++--------- .../TokenAcquisition.cs | 2 ++ .../TokenAcquisitionOptions.cs | 8 ++++++++ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index f634f6d03..3763c041a 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -672,7 +672,7 @@ - todo. + Options passed-in to create the token acquisition object which calls into MSAL .NET. @@ -904,7 +904,7 @@ Optional claims principal representing the user. If not provided, will use the signed-in user (in a web app), or the user for which the token was received (in a web API) cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. - + Options passed-in to create the token acquisition object which calls into MSAL .NET. An access token to call on behalf of the user, the downstream API characterized by its scopes. @@ -920,7 +920,7 @@ Optional claims principal representing the user. If not provided, will use the signed-in user (in a web app), or the user for which the token was received (in a web API) cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. - + Options passed-in to create the token acquisition object which calls into MSAL .NET. An to call on behalf of the user, the downstream API characterized by its scopes. @@ -935,7 +935,7 @@ several calls to get tokens for other resources). Enables overriding of the tenant/account for the same identity. This is useful in the cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. - + Options passed-in to create the token acquisition object which calls into MSAL .NET. An access token for the app itself, based on its scopes. @@ -1540,7 +1540,7 @@ Optional claims principal representing the user. If not provided, will use the signed-in user (in a web app), or the user for which the token was received (in a web API) cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. - + Options passed-in to create the token acquisition object which calls into MSAL .NET. An access token to call the downstream API and populated with this downstream API's scopes. Calling this method from a web API supposes that you have previously called, in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method @@ -1560,7 +1560,7 @@ several calls to get tokens for other resources). Enables overriding of the tenant/account for the same identity. This is useful for multi tenant apps or daemons. - + Options passed-in to create the token acquisition object which calls into MSAL .NET. An access token for the app itself, based on its scopes. @@ -1579,7 +1579,7 @@ Optional claims principal representing the user. If not provided, will use the signed-in user (in a web app), or the user for which the token was received (in a web API) cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. - + Options passed-in to create the token acquisition object which calls into MSAL .NET. An access token to call the downstream API and populated with this downstream API's scopes. Calling this method from a web API supposes that you have previously called, in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method @@ -1626,6 +1626,7 @@ (optional) Authority based on a specific tenant for which to acquire a token to access the scopes on behalf of the user described in the claimsPrincipal. Azure AD B2C user flow to target. + Options passed-in to create the token acquisition object which calls into MSAL .NET. @@ -1638,11 +1639,11 @@ Authority based on a specific tenant for which to acquire a token to access the scopes on behalf of the user. Azure AD B2C user flow. - + Options passed-in to create the token acquisition object which calls into MSAL .NET. - Options passed-in to create the token acquisition object with calls into MSAL .NET. + Options passed-in to create the token acquisition object which calls into MSAL .NET. diff --git a/src/Microsoft.Identity.Web/TokenAcquisition.cs b/src/Microsoft.Identity.Web/TokenAcquisition.cs index e151c2e4c..d2ca09ed7 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisition.cs @@ -290,6 +290,7 @@ public async Task GetAccessTokenForAppAsync( { builder.WithExtraQueryParameters(tokenAcquisitionOptions.ExtraQueryParameters); builder.WithCorrelationId(tokenAcquisitionOptions.CorrelationId); + builder.WithForceRefresh(tokenAcquisitionOptions.ForceRefresh); } result = await builder.ExecuteAsync() @@ -630,6 +631,7 @@ private async Task GetAuthenticationResultForWebAppWithAcc { builder.WithExtraQueryParameters(tokenAcquisitionOptions.ExtraQueryParameters); builder.WithCorrelationId(tokenAcquisitionOptions.CorrelationId); + builder.WithForceRefresh(tokenAcquisitionOptions.ForceRefresh); } // Acquire an access token as a B2C authority diff --git a/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs b/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs index ec7b09ef3..20071d5d6 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs @@ -22,6 +22,13 @@ public class TokenAcquisitionOptions /// public Dictionary? ExtraQueryParameters { get; set; } = null; + /// + /// Specifies if the token request will ignore the access token in the token cache + /// and will attempt to acquire a new access token. + /// If true, the request will ignore the token cache. The default is false. + /// + public bool ForceRefresh { get; set; } = false; + /// /// Clone the options (to be able to override them). /// @@ -32,6 +39,7 @@ public TokenAcquisitionOptions Clone() { CorrelationId = CorrelationId, ExtraQueryParameters = ExtraQueryParameters, + ForceRefresh = ForceRefresh, }; } } From 221775e88f8309631b5ae3a4a2af685c18ff6030 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 21 Sep 2020 09:23:51 -0700 Subject: [PATCH 4/8] update test --- .../AcquireTokenForUserIntegrationTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs index 83eb45de3..4b58ed440 100644 --- a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs +++ b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs @@ -10,11 +10,13 @@ using IntegrationTestService; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Graph; using Microsoft.Identity.Client; using Microsoft.Identity.Web.Test.Common; using Microsoft.Identity.Web.Test.LabInfrastructure; using Microsoft.Identity.Web.TokenCacheProviders.Distributed; using Microsoft.Identity.Web.TokenCacheProviders.InMemory; +using Microsoft.Rest; using Xunit; namespace Microsoft.Identity.Web.Test.Integration @@ -34,9 +36,9 @@ public AcquireTokenForUserIntegrationTests(WebApplicationFactory factor [InlineData(TestConstants.SecurePageCallDownstreamWebApi)] [InlineData(TestConstants.SecurePageCallDownstreamWebApiGeneric)] [InlineData(TestConstants.SecurePageCallMicrosoftGraph)] - [InlineData(TestConstants.SecurePageGetTokenAsync, false)] + // [InlineData(TestConstants.SecurePageGetTokenAsync, false)] // [InlineData(TestConstants.SecurePageCallDownstreamWebApi, false)] - // [InlineData(TestConstants.SecurePageCallDownstreamWebApiGeneric, false)] + [InlineData(TestConstants.SecurePageCallDownstreamWebApiGeneric, false)] // [InlineData(TestConstants.SecurePageCallMicrosoftGraph, false)] public async Task GetTokenForUserAsync( string webApiUrl, @@ -79,13 +81,11 @@ public async Task GetTokenForUserAsync( "{0} {1}", Constants.Bearer, result.AccessToken)); - response = await client.SendAsync(httpRequestMessage).ConfigureAwait(false); } // Assert Assert.True(response.IsSuccessStatusCode); - Assert.Equal(TestConstants.s_correlationId, result.CorrelationId); } private static async Task AcquireTokenForLabUserAsync() From 28ec7ca55b9ef34fc5015118a32f93993b36ac14 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 21 Sep 2020 09:24:45 -0700 Subject: [PATCH 5/8] remove using --- .../AcquireTokenForUserIntegrationTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs index 4b58ed440..503edfc00 100644 --- a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs +++ b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs @@ -16,7 +16,6 @@ using Microsoft.Identity.Web.Test.LabInfrastructure; using Microsoft.Identity.Web.TokenCacheProviders.Distributed; using Microsoft.Identity.Web.TokenCacheProviders.InMemory; -using Microsoft.Rest; using Xunit; namespace Microsoft.Identity.Web.Test.Integration @@ -36,7 +35,7 @@ public AcquireTokenForUserIntegrationTests(WebApplicationFactory factor [InlineData(TestConstants.SecurePageCallDownstreamWebApi)] [InlineData(TestConstants.SecurePageCallDownstreamWebApiGeneric)] [InlineData(TestConstants.SecurePageCallMicrosoftGraph)] - // [InlineData(TestConstants.SecurePageGetTokenAsync, false)] + [InlineData(TestConstants.SecurePageGetTokenAsync, false)] // [InlineData(TestConstants.SecurePageCallDownstreamWebApi, false)] [InlineData(TestConstants.SecurePageCallDownstreamWebApiGeneric, false)] // [InlineData(TestConstants.SecurePageCallMicrosoftGraph, false)] From 07efd3f66a2df0de4b7bd90ee306e88854b5c24c Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 21 Sep 2020 10:17:25 -0700 Subject: [PATCH 6/8] add force refresh + test --- .../Microsoft.Identity.Web.xml | 7 +++++++ .../Controllers/WeatherForecastController.cs | 20 +++++++++++++++++-- .../TestConstants.cs | 1 + .../AcquireTokenForUserIntegrationTests.cs | 3 ++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 3763c041a..08c882bb4 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1657,6 +1657,13 @@ Sets Extra Query Parameters for the query string in the HTTP authentication request. + + + Specifies if the token request will ignore the access token in the token cache + and will attempt to acquire a new access token. + If true, the request will ignore the token cache. The default is false. + + Clone the options (to be able to override them). diff --git a/tests/IntegrationTests/IntegrationTestService/Controllers/WeatherForecastController.cs b/tests/IntegrationTests/IntegrationTestService/Controllers/WeatherForecastController.cs index d1a154e13..9de5ae45b 100644 --- a/tests/IntegrationTests/IntegrationTestService/Controllers/WeatherForecastController.cs +++ b/tests/IntegrationTests/IntegrationTestService/Controllers/WeatherForecastController.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -56,8 +57,6 @@ public async Task CallDownstreamWebApiGenericAsync() null, options => { options.RelativePath = "me"; - options.TokenAcquisitionOptions.CorrelationId = TestConstants.s_correlationId; - options.TokenAcquisitionOptions.ExtraQueryParameters = TestConstants.ExtraQueryParameters; }); return user.DisplayName; } @@ -69,5 +68,22 @@ public async Task CallMicrosoftGraphAsync() var user = await _graphServiceClient.Me.Request().GetAsync(); return user.DisplayName; } + + [HttpGet(TestConstants.SecurePageCallDownstreamWebApiGenericWithTokenAcquisitionOptions)] + public async Task CallDownstreamWebApiGenericWithTokenAcquisitionOptionsAsync() + { + HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi); + var user = await _downstreamWebApi.CallWebApiForUserAsync( + TestConstants.SectionNameCalledApi, + null, + options => { + options.RelativePath = "me"; + options.TokenAcquisitionOptions.CorrelationId = TestConstants.s_correlationId; + options.TokenAcquisitionOptions.ExtraQueryParameters = new Dictionary() + { { "slice", "testslice" } }; + options.TokenAcquisitionOptions.ForceRefresh = true; + }); + return user.DisplayName; + } } } diff --git a/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs b/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs index 78bf3695b..3c74e1502 100644 --- a/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs +++ b/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs @@ -127,6 +127,7 @@ public static class TestConstants public const string SecurePageGetTokenAsync = "/SecurePage/GetTokenAsync"; public const string SecurePageCallDownstreamWebApi = "/SecurePage/CallDownstreamWebApiAsync"; public const string SecurePageCallDownstreamWebApiGeneric = "/SecurePage/CallDownstreamWebApiGenericAsync"; + public const string SecurePageCallDownstreamWebApiGenericWithTokenAcquisitionOptions = "/SecurePage/CallDownstreamWebApiGenericWithTokenAcquisitionOptionsAsync"; public const string SecurePageCallMicrosoftGraph = "/SecurePage/CallMicrosoftGraph"; public const string SectionNameCalledApi = "CalledApi"; diff --git a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs index 503edfc00..683f45cdf 100644 --- a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs +++ b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForUserIntegrationTests.cs @@ -35,9 +35,10 @@ public AcquireTokenForUserIntegrationTests(WebApplicationFactory factor [InlineData(TestConstants.SecurePageCallDownstreamWebApi)] [InlineData(TestConstants.SecurePageCallDownstreamWebApiGeneric)] [InlineData(TestConstants.SecurePageCallMicrosoftGraph)] + [InlineData(TestConstants.SecurePageCallDownstreamWebApiGenericWithTokenAcquisitionOptions)] [InlineData(TestConstants.SecurePageGetTokenAsync, false)] // [InlineData(TestConstants.SecurePageCallDownstreamWebApi, false)] - [InlineData(TestConstants.SecurePageCallDownstreamWebApiGeneric, false)] + // [InlineData(TestConstants.SecurePageCallDownstreamWebApiGeneric, false)] // [InlineData(TestConstants.SecurePageCallMicrosoftGraph, false)] public async Task GetTokenForUserAsync( string webApiUrl, From 3dafa34862bbb4591da8e71e99b3e899005b8ed3 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 21 Sep 2020 10:21:02 -0700 Subject: [PATCH 7/8] remove unused variable --- .../TestConstants.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs b/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs index 3c74e1502..f74cb3c5a 100644 --- a/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs +++ b/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs @@ -141,19 +141,6 @@ public static class TestConstants public const string Headless = "headless"; // TokenAcqusitionOptions - public static Dictionary ExtraQueryParameters - { - get - { - return new Dictionary() - { - { "extra", "qp" }, - { "key1", "value1%20with%20encoded%20space" }, - { "key2", "value2" }, - }; - } - } - public static Guid s_correlationId = new Guid("6347d33d-941a-4c35-9912-a9cf54fb1b3e"); } } From 82b483559390b61b7929723641e3ec1211508886 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 21 Sep 2020 12:42:40 -0700 Subject: [PATCH 8/8] PR feedback --- src/Microsoft.Identity.Web/TokenAcquisition.cs | 4 +--- src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Identity.Web/TokenAcquisition.cs b/src/Microsoft.Identity.Web/TokenAcquisition.cs index aea317d93..de0890544 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisition.cs @@ -184,9 +184,7 @@ public async Task AddAccountToCacheFromAuthorizationCodeAsync( /// Optional claims principal representing the user. If not provided, will use the signed-in /// user (in a web app), or the user for which the token was received (in a web API) /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest. - /// Options passed-in to create the token acquisition object which calls into MSAL .NET. - /// user (in a web app), or the user for which the token was received (in a web API), or - /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest . + /// Options passed-in to create the token acquisition options object which calls into MSAL .NET. /// An access token to call the downstream API and populated with this downstream API's scopes. /// Calling this method from a web API supposes that you have previously called, /// in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method diff --git a/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs b/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs index 20071d5d6..1a614644d 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisitionOptions.cs @@ -26,6 +26,8 @@ public class TokenAcquisitionOptions /// Specifies if the token request will ignore the access token in the token cache /// and will attempt to acquire a new access token. /// If true, the request will ignore the token cache. The default is false. + /// Use this option with care and only when needed, for instance, if you know that conditional access policies have changed, + /// for it induces performance degradation, as the token cache is not utilized. /// public bool ForceRefresh { get; set; } = false;