Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@

<PropertyGroup Label="Common dependency versions">
<MicrosoftIdentityModelVersion Condition="'$(MicrosoftIdentityModelVersion)' == ''">8.14.0</MicrosoftIdentityModelVersion>
<MicrosoftIdentityClientVersion Condition="'$(MicrosoftIdentityClientVersion)' == ''">4.77.1</MicrosoftIdentityClientVersion>
<MicrosoftIdentityClientVersion Condition="'$(MicrosoftIdentityClientVersion)' == ''">4.82.0</MicrosoftIdentityClientVersion>
<MicrosoftIdentityAbstractionsVersion Condition="'$(MicrosoftIdentityAbstractionsVersion)' == ''">9.5.0</MicrosoftIdentityAbstractionsVersion>
<FxCopAnalyzersVersion>3.3.0</FxCopAnalyzersVersion>
<SystemTextEncodingsWebVersion>4.7.2</SystemTextEncodingsWebVersion>
Expand Down
60 changes: 56 additions & 4 deletions src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -154,7 +155,9 @@ public async Task<AcquireTokenResult> AddAccountToCacheFromAuthorizationCodeAsyn

if (mergedOptions.ExtraQueryParameters != null)
{
#pragma warning disable CS0618 // Type or member is obsolete
builder.WithExtraQueryParameters((Dictionary<string, string>)mergedOptions.ExtraQueryParameters);
#pragma warning restore CS0618 // Type or member is obsolete
}

if (!string.IsNullOrEmpty(authCodeRedemptionParameters.Tenant))
Expand Down Expand Up @@ -210,16 +213,16 @@ public async Task<AcquireTokenResult> AddAccountToCacheFromAuthorizationCodeAsyn
}
}


/// <summary>
/// Allows creation of confidential client applications targeting regional and global authorities
/// when supporting managed identities.
/// </summary>
/// <param name="mergedOptions">Merged configuration options</param>
/// <param name="mergedOptions">Merged configuration options.</param>
/// <returns>Concatenated string of authority, cliend id and azure region</returns>
private static string GetApplicationKey(MergedOptions mergedOptions)
{
string credentialId = string.Join("-", mergedOptions.ClientCredentials?.Select(c => c.Id) ?? Enumerable.Empty<string>());

return DefaultTokenAcquirerFactoryImplementation.GetKey(mergedOptions.Authority, mergedOptions.ClientId, mergedOptions.AzureRegion) + credentialId;
}

Expand Down Expand Up @@ -258,7 +261,6 @@ public async Task<AuthenticationResult> GetAuthenticationResultForUserAsync(
_ = Throws.IfNull(scopes);

MergedOptions mergedOptions = GetMergedOptions(authenticationScheme, tokenAcquisitionOptions);

user ??= await _tokenAcquisitionHost.GetAuthenticatedUserAsync(user).ConfigureAwait(false);

var application = await GetOrBuildConfidentialClientApplicationAsync(mergedOptions);
Expand Down Expand Up @@ -433,7 +435,9 @@ public async Task<AuthenticationResult> GetAuthenticationResultForUserAsync(
var dict = MergeExtraQueryParameters(mergedOptions, tokenAcquisitionOptions);
if (dict != null)
{
#pragma warning disable CS0618 // Type or member is obsolete
builder.WithExtraQueryParameters(dict);
#pragma warning restore CS0618 // Type or member is obsolete
}

if (tokenAcquisitionOptions.ExtraHeadersParameters != null)
Expand All @@ -445,6 +449,11 @@ public async Task<AuthenticationResult> GetAuthenticationResultForUserAsync(
builder.WithCorrelationId(tokenAcquisitionOptions.CorrelationId.Value);
}
builder.WithClaims(tokenAcquisitionOptions.Claims);
var clientClaims = GetClientClaimsIfExist(tokenAcquisitionOptions);
if (clientClaims != null)
{
builder.WithExtraClientAssertionClaims(clientClaims);
}
if (tokenAcquisitionOptions.PoPConfiguration != null)
{
builder.WithSignedHttpRequestProofOfPossession(tokenAcquisitionOptions.PoPConfiguration);
Expand Down Expand Up @@ -560,6 +569,13 @@ public async Task<AuthenticationResult> GetAuthenticationResultForAppAsync(
miBuilder.WithClaims(tokenAcquisitionOptions.Claims);
}

//TODO: Should client assertion claims be supported for managed identity?
//var clientClaims = GetClientClaimsIfExist(tokenAcquisitionOptions);
//if (clientClaims != null)
//{
// miBuilder.WithExtraClientAssertionClaims(clientClaims);
//}

return await miBuilder.ExecuteAsync().ConfigureAwait(false);
}
catch (Exception ex)
Expand Down Expand Up @@ -618,7 +634,9 @@ public async Task<AuthenticationResult> GetAuthenticationResultForAppAsync(

if (dict != null)
{
#pragma warning disable CS0618 // Type or member is obsolete
builder.WithExtraQueryParameters(dict);
#pragma warning restore CS0618 // Type or member is obsolete
}
if (tokenAcquisitionOptions.ExtraHeadersParameters != null)
{
Expand All @@ -635,6 +653,13 @@ public async Task<AuthenticationResult> GetAuthenticationResultForAppAsync(
}
builder.WithForceRefresh(tokenAcquisitionOptions.ForceRefresh);
builder.WithClaims(tokenAcquisitionOptions.Claims);

var clientClaims = GetClientClaimsIfExist(tokenAcquisitionOptions);
if (clientClaims != null)
{
builder.WithExtraClientAssertionClaims(JsonSerializer.Serialize(clientClaims));
}

if (!string.IsNullOrEmpty(tokenAcquisitionOptions.FmiPath))
{
builder.WithFmiPath(tokenAcquisitionOptions.FmiPath);
Expand Down Expand Up @@ -896,9 +921,22 @@ private bool IsInvalidClientCertificateOrSignedAssertionError(MsalServiceExcepti
);
}

private static string? GetClientClaimsIfExist(TokenAcquisitionOptions? tokenAcquisitionOptions)
{
IDictionary<string, string>? clientClaims = null;
if (tokenAcquisitionOptions is not null && tokenAcquisitionOptions.ExtraParameters is not null &&
tokenAcquisitionOptions.ExtraParameters["IDWEB_CLIENT_CLAIMS"] is not null)
{
clientClaims = tokenAcquisitionOptions.ExtraParameters["IDWEB_CLIENT_CLAIMS"] as IDictionary<string, string>;
}
return JsonSerializer.Serialize(clientClaims);
}

#pragma warning disable RS0051 // Add internal types and members to the declared API
internal /* for testing */ async Task<IConfidentialClientApplication> GetOrBuildConfidentialClientApplicationAsync(
MergedOptions mergedOptions)
#pragma warning restore RS0051 // Add internal types and members to the declared API
MergedOptions mergedOptions,
TokenAcquisitionOptions? tokenAcquisitionOptions = null) // just for PoC will drive this through MergedOptions later
{
string key = GetApplicationKey(mergedOptions);

Expand Down Expand Up @@ -1165,7 +1203,9 @@ private void NotifyCertificateSelection(
dict.Remove(subAssertionConstant);
}

#pragma warning disable CS0618 // Type or member is obsolete
builder.WithExtraQueryParameters(dict);
#pragma warning restore CS0618 // Type or member is obsolete
}
if (tokenAcquisitionOptions.ExtraHeadersParameters != null)
{
Expand All @@ -1177,6 +1217,11 @@ private void NotifyCertificateSelection(
}
builder.WithForceRefresh(tokenAcquisitionOptions.ForceRefresh);
builder.WithClaims(tokenAcquisitionOptions.Claims);
var clientClaims = GetClientClaimsIfExist(tokenAcquisitionOptions);
if (clientClaims != null)
{
builder.WithExtraClientAssertionClaims(clientClaims);
}
if (tokenAcquisitionOptions.PoPConfiguration != null)
{
builder.WithSignedHttpRequestProofOfPossession(tokenAcquisitionOptions.PoPConfiguration);
Expand Down Expand Up @@ -1322,7 +1367,9 @@ private Task<AuthenticationResult> GetAuthenticationResultForWebAppWithAccountFr

if (dict != null)
{
#pragma warning disable CS0618 // Type or member is obsolete
builder.WithExtraQueryParameters(dict);
#pragma warning restore CS0618 // Type or member is obsolete
}
if (tokenAcquisitionOptions.ExtraHeadersParameters != null)
{
Expand All @@ -1334,6 +1381,11 @@ private Task<AuthenticationResult> GetAuthenticationResultForWebAppWithAccountFr
}
builder.WithForceRefresh(tokenAcquisitionOptions.ForceRefresh);
builder.WithClaims(tokenAcquisitionOptions.Claims);
var clientClaims = GetClientClaimsIfExist(tokenAcquisitionOptions);
if (clientClaims != null)
{
builder.WithExtraClientAssertionClaims(clientClaims);
}
if (tokenAcquisitionOptions.PoPConfiguration != null)
{
builder.WithProofOfPossession(tokenAcquisitionOptions.PoPConfiguration);
Expand Down
Loading