Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
using Microsoft.Identity.Client.Utils;
using Microsoft.Identity.Client.Extensibility;
using Microsoft.Identity.Client.OAuth2;
using System.Security.Cryptography;
using System.Text;

namespace Microsoft.Identity.Client
{
Expand Down Expand Up @@ -44,9 +46,9 @@ internal static AcquireTokenForClientParameterBuilder Create(

if (!string.IsNullOrEmpty(confidentialClientApplicationExecutor.ServiceBundle.Config.CertificateIdToAssociateWithToken))
{
builder.WithAdditionalCacheKeyComponents(new SortedList<string, string>
builder.WithAdditionalCacheKeyComponents(new SortedList<string, Func<CancellationToken, Task<string>>>
{
{ Constants.CertSerialNumber, confidentialClientApplicationExecutor.ServiceBundle.Config.CertificateIdToAssociateWithToken }
{ Constants.CertSerialNumber, (CancellationToken ct) => { return Task.FromResult(confidentialClientApplicationExecutor.ServiceBundle.Config.CertificateIdToAssociateWithToken); } }
});
}

Expand Down Expand Up @@ -113,6 +115,28 @@ public AcquireTokenForClientParameterBuilder WithMtlsProofOfPossession()
return this;
}

/// <summary>
/// Add extra body parameters to the token request. These parameters are added to the cache key to associate these parameters with the acquired token.
/// </summary>
/// <param name="extrabodyparams">List of additional body parameters</param>
/// <returns></returns>
public AcquireTokenForClientParameterBuilder WithExtraBodyParameters (Dictionary<string, Func<CancellationToken, Task<string>>> extrabodyparams)
{
this.OnBeforeTokenRequest(async (data) =>
{
foreach (var param in extrabodyparams)
{
if (param.Value != null)
{
data.BodyParameters.Add(param.Key, await param.Value(data.CancellationToken).ConfigureAwait(false));
}
}
});

this.WithAdditionalCacheKeyComponents(extrabodyparams);
return this;
}

/// <summary>
/// Please use WithAzureRegion on the ConfidentialClientApplicationBuilder object
/// </summary>
Expand Down Expand Up @@ -143,9 +167,9 @@ public AcquireTokenForClientParameterBuilder WithFmiPath(string pathSuffix)
throw new ArgumentNullException(nameof(pathSuffix));
}

var cacheKey = new SortedList<string, string>
var cacheKey = new SortedList<string, Func<CancellationToken, Task<string>>>
{
{ OAuth2Parameter.FmiPath, pathSuffix }
{ OAuth2Parameter.FmiPath, (CancellationToken ct) => {return Task.FromResult(pathSuffix);} }
};

this.WithAdditionalCacheKeyComponents(cacheKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
var requestParameters = await _clientApplicationBase.CreateRequestParametersAsync(
commonParameters,
requestContext,
_clientApplicationBase.UserTokenCacheInternal).ConfigureAwait(false);
_clientApplicationBase.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

requestParameters.SendX5C = silentParameters.SendX5C ?? false;

Expand All @@ -59,7 +60,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
var requestParameters = await _clientApplicationBase.CreateRequestParametersAsync(
commonParameters,
requestContext,
_clientApplicationBase.UserTokenCacheInternal).ConfigureAwait(false);
_clientApplicationBase.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

requestContext.Logger.Info(() => LogMessages.UsingXScopesForRefreshTokenRequest(commonParameters.Scopes.Count()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
AuthenticationRequestParameters requestParams = await _confidentialClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_confidentialClientApplication.UserTokenCacheInternal).ConfigureAwait(false);
_confidentialClientApplication.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);
requestParams.SendX5C = authorizationCodeParameters.SendX5C ?? false;

var handler = new ConfidentialAuthCodeRequest(
Expand All @@ -60,7 +61,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
AuthenticationRequestParameters requestParams = await _confidentialClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_confidentialClientApplication.AppTokenCacheInternal).ConfigureAwait(false);
_confidentialClientApplication.AppTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

requestParams.SendX5C = clientParameters.SendX5C ?? false;

Expand All @@ -82,7 +84,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
AuthenticationRequestParameters requestParams = await _confidentialClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_confidentialClientApplication.UserTokenCacheInternal).ConfigureAwait(false);
_confidentialClientApplication.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

requestParams.SendX5C = onBehalfOfParameters.SendX5C ?? false;
requestParams.UserAssertion = onBehalfOfParameters.UserAssertion;
Expand All @@ -106,7 +109,8 @@ public async Task<Uri> ExecuteAsync(
AuthenticationRequestParameters requestParameters = await _confidentialClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_confidentialClientApplication.UserTokenCacheInternal).ConfigureAwait(false);
_confidentialClientApplication.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

requestParameters.Account = authorizationRequestUrlParameters.Account;
requestParameters.LoginHint = authorizationRequestUrlParameters.LoginHint;
Expand Down Expand Up @@ -142,7 +146,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
AuthenticationRequestParameters requestParams = await _confidentialClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_confidentialClientApplication.UserTokenCacheInternal).ConfigureAwait(false);
_confidentialClientApplication.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

requestParams.SendX5C = usernamePasswordParameters.SendX5C ?? false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
var requestParams = await _managedIdentityApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_managedIdentityApplication.AppTokenCacheInternal).ConfigureAwait(false);
_managedIdentityApplication.AppTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

var handler = new ManagedIdentityAuthRequest(
ServiceBundle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
AuthenticationRequestParameters requestParams = await _publicClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_publicClientApplication.UserTokenCacheInternal).ConfigureAwait(false);
_publicClientApplication.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

requestParams.LoginHint = interactiveParameters.LoginHint;
requestParams.Account = interactiveParameters.Account;
Expand All @@ -52,7 +53,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
var requestParams = await _publicClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_publicClientApplication.UserTokenCacheInternal).ConfigureAwait(false);
_publicClientApplication.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

var handler = new DeviceCodeRequest(
ServiceBundle,
Expand All @@ -72,7 +74,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
var requestParams = await _publicClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_publicClientApplication.UserTokenCacheInternal).ConfigureAwait(false);
_publicClientApplication.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

var handler = new IntegratedWindowsAuthRequest(
ServiceBundle,
Expand All @@ -92,7 +95,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
var requestParams = await _publicClientApplication.CreateRequestParametersAsync(
commonParameters,
requestContext,
_publicClientApplication.UserTokenCacheInternal).ConfigureAwait(false);
_publicClientApplication.UserTokenCacheInternal,
cancellationToken).ConfigureAwait(false);

var handler = new UsernamePasswordRequest(
ServiceBundle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client.AppConfig;
using Microsoft.Identity.Client.AuthScheme;
Expand All @@ -27,10 +28,10 @@ internal class AcquireTokenCommonParameters
public IAuthenticationOperation AuthenticationOperation { get; set; } = new BearerAuthenticationOperation();
public IDictionary<string, string> ExtraHttpHeaders { get; set; }
public PoPAuthenticationConfiguration PopAuthenticationConfiguration { get; set; }
public Func<OnBeforeTokenRequestData, Task> OnBeforeTokenRequestHandler { get; internal set; }
public IList<Func<OnBeforeTokenRequestData, Task>> OnBeforeTokenRequestHandler { get; internal set; }
public X509Certificate2 MtlsCertificate { get; internal set; }
public List<string> AdditionalCacheParameters { get; set; }
public SortedList<string, string> CacheKeyComponents { get; internal set; }
public SortedList<string, Func<CancellationToken, Task<string>>> CacheKeyComponents { get; internal set; }
public string FmiPathSuffix { get; internal set; }
public string ClientAssertionFmiPath { get; internal set; }
}
Expand Down
26 changes: 25 additions & 1 deletion src/client/Microsoft.Identity.Client/ApplicationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client.ApiConfig.Parameters;
using Microsoft.Identity.Client.Internal;
Expand All @@ -27,12 +29,15 @@ internal ApplicationBase(ApplicationConfiguration config)
internal virtual async Task<AuthenticationRequestParameters> CreateRequestParametersAsync(
AcquireTokenCommonParameters commonParameters,
RequestContext requestContext,
ITokenCacheInternal cache)
ITokenCacheInternal cache,
CancellationToken cancellationToken)
{
Instance.Authority authority = await Instance.Authority.CreateAuthorityForRequestAsync(
requestContext,
commonParameters.AuthorityOverride).ConfigureAwait(false);

await InitializeCacheKeyComponentsAsync(cancellationToken, commonParameters.CacheKeyComponents).ConfigureAwait(false);

return new AuthenticationRequestParameters(
ServiceBundle,
cache,
Expand All @@ -41,6 +46,25 @@ internal virtual async Task<AuthenticationRequestParameters> CreateRequestParame
authority);
}

internal async Task<SortedList<string, string>> InitializeCacheKeyComponentsAsync(CancellationToken cancellationToken, SortedList<string, Func<CancellationToken, Task<string>>> cacheKeyComponents)
{
if (cacheKeyComponents != null && cacheKeyComponents.Count > 0)
{
var initializedCacheKeyComponents = new SortedList<string, string>();

foreach (var kvp in cacheKeyComponents)
{
if (kvp.Value != null)
{
initializedCacheKeyComponents.Add(kvp.Key, await kvp.Value.Invoke(cancellationToken).ConfigureAwait(false));
}
}
return initializedCacheKeyComponents;
}

return null;
}

internal static void GuardMobileFrameworks()
{
#if ANDROID || iOS || MAC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,10 @@ AcquireTokenByRefreshTokenParameterBuilder IByRefreshToken.AcquireTokenByRefresh
internal override async Task<AuthenticationRequestParameters> CreateRequestParametersAsync(
AcquireTokenCommonParameters commonParameters,
RequestContext requestContext,
ITokenCacheInternal cache)
ITokenCacheInternal cache,
CancellationToken cancellationToken)
{
AuthenticationRequestParameters requestParams = await base.CreateRequestParametersAsync(commonParameters, requestContext, cache).ConfigureAwait(false);
AuthenticationRequestParameters requestParams = await base.CreateRequestParametersAsync(commonParameters, requestContext, cache, cancellationToken).ConfigureAwait(false);
return requestParams;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client.OAuth2;

Expand Down Expand Up @@ -34,7 +35,14 @@ public static AbstractAcquireTokenParameterBuilder<T> OnBeforeTokenRequest<T>(
throw new InvalidOperationException("Cannot set OnBeforeTokenRequest handler twice.");
}

builder.CommonParameters.OnBeforeTokenRequestHandler = onBeforeTokenRequestHandler;
if (builder.CommonParameters.OnBeforeTokenRequestHandler == null)
{
builder.CommonParameters.OnBeforeTokenRequestHandler = new List<Func<OnBeforeTokenRequestData, Task>> { onBeforeTokenRequestHandler };
}
else
{
builder.CommonParameters.OnBeforeTokenRequestHandler.Add(onBeforeTokenRequestHandler);
}

return builder;
}
Expand Down Expand Up @@ -80,7 +88,14 @@ public static AbstractAcquireTokenParameterBuilder<T> WithAuthenticationExtensio
throw new InvalidOperationException("Cannot set both an AuthenticaitonOperation and an OnBeforeTokenRequestHandler");
}

builder.CommonParameters.OnBeforeTokenRequestHandler = authenticationExtension.OnBeforeTokenRequestHandler;
if (builder.CommonParameters.OnBeforeTokenRequestHandler == null)
{
builder.CommonParameters.OnBeforeTokenRequestHandler = new List<Func<OnBeforeTokenRequestData, Task>> { authenticationExtension.OnBeforeTokenRequestHandler };
}
else
{
builder.CommonParameters.OnBeforeTokenRequestHandler.Add(authenticationExtension.OnBeforeTokenRequestHandler);
}

if (authenticationExtension.AuthenticationOperation != null)
builder.WithAuthenticationOperation(authenticationExtension.AuthenticationOperation);
Expand Down Expand Up @@ -137,7 +152,7 @@ public static AbstractAcquireTokenParameterBuilder<T> WithAdditionalCacheParamet
/// </remarks>
internal static AbstractAcquireTokenParameterBuilder<T> WithAdditionalCacheKeyComponents<T>(
this AbstractAcquireTokenParameterBuilder<T> builder,
IDictionary<string, string> cacheKeyComponents)
IDictionary<string, Func<CancellationToken, Task<string>>> cacheKeyComponents)
where T : AbstractAcquireTokenParameterBuilder<T>
{
if (cacheKeyComponents == null || cacheKeyComponents.Count == 0)
Expand All @@ -148,7 +163,7 @@ internal static AbstractAcquireTokenParameterBuilder<T> WithAdditionalCacheKeyCo

if (builder.CommonParameters.CacheKeyComponents == null)
{
builder.CommonParameters.CacheKeyComponents = new SortedList<string, string>(cacheKeyComponents);
builder.CommonParameters.CacheKeyComponents = new SortedList<string, Func<CancellationToken, Task<string>>>(cacheKeyComponents);
}
else
{
Expand Down Expand Up @@ -187,9 +202,9 @@ public static AbstractAcquireTokenParameterBuilder<T> WithFmiPathForClientAssert
builder.CommonParameters.ClientAssertionFmiPath = fmiPath;

// Add the fmi_path to the cache key so that it is used for cache lookups
var cacheKey = new SortedList<string, string>
var cacheKey = new SortedList<string, Func<CancellationToken, Task<string>>>
{
{ "credential_fmi_path", fmiPath }
{ "credential_fmi_path", (CancellationToken ct) => Task.FromResult(fmiPath) }
};

WithAdditionalCacheKeyComponents(builder, cacheKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public AuthenticationRequestParameters(
AcquireTokenCommonParameters commonParameters,
RequestContext requestContext,
Authority initialAuthority,
string homeAccountId = null)
string homeAccountId = null,
SortedList<string, string> cacheKeyComponents = null)
{
_serviceBundle = serviceBundle;
_commonParameters = commonParameters;
Expand Down Expand Up @@ -73,6 +74,7 @@ public AuthenticationRequestParameters(
_serviceBundle.Config.ClientCapabilities);

HomeAccountId = homeAccountId;
CacheKeyComponents = cacheKeyComponents;
}

public ApplicationConfiguration AppConfig => _serviceBundle.Config;
Expand Down Expand Up @@ -127,7 +129,7 @@ public string Claims

public IEnumerable<string> PersistedCacheParameters => _commonParameters.AdditionalCacheParameters;

public SortedList<string, string> CacheKeyComponents => _commonParameters.CacheKeyComponents;
public SortedList<string, string> CacheKeyComponents {get; private set; }

#region TODO REMOVE FROM HERE AND USE FROM SPECIFIC REQUEST PARAMETERS
// TODO: ideally, these can come from the particular request instance and not be in RequestBase since it's not valid for all requests.
Expand Down Expand Up @@ -156,7 +158,7 @@ public string LoginHint
/// <summary>
/// If set, MSAL should add the key / value pairs from the provider to the token endpoint instead of generating a client assertion
/// </summary>
public Func<OnBeforeTokenRequestData, Task> OnBeforeTokenRequestHandler { get => _commonParameters.OnBeforeTokenRequestHandler; }
public IList<Func<OnBeforeTokenRequestData, Task>> OnBeforeTokenRequestHandler { get => _commonParameters.OnBeforeTokenRequestHandler; }

public IDictionary<string, string> ExtraHttpHeaders => _commonParameters.ExtraHttpHeaders;

Expand Down
Loading