Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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 @@ -25,12 +25,15 @@ public static ConfidentialClientApplicationBuilder WithClientCredentials(
credentialSourceLoaderParameters).GetAwaiter().GetResult();
}

#pragma warning disable RS0051
public static async Task<ConfidentialClientApplicationBuilder> WithClientCredentialsAsync(
this ConfidentialClientApplicationBuilder builder,
IEnumerable<CredentialDescription> clientCredentials,
ILogger logger,
ICredentialsLoader credentialsLoader,
CredentialSourceLoaderParameters? credentialSourceLoaderParameters)
CredentialSourceLoaderParameters? credentialSourceLoaderParameters,
IDictionary<string, string>? clientClaims = null)
#pragma warning restore RS0051
{
var credential = await LoadCredentialForMsalOrFailAsync(
clientCredentials,
Expand All @@ -49,7 +52,7 @@ public static async Task<ConfidentialClientApplicationBuilder> WithClientCredent
case CredentialType.SignedAssertion:
return builder.WithClientAssertion((credential.CachedValue as ClientAssertionProviderBase)!.GetSignedAssertionAsync);
case CredentialType.Certificate:
return builder.WithCertificate(credential.Certificate);
return builder.WithCertificateInternal(credential, clientClaims);
case CredentialType.Secret:
return builder.WithClientSecret(credential.ClientSecret);
default:
Expand All @@ -58,6 +61,18 @@ public static async Task<ConfidentialClientApplicationBuilder> WithClientCredent
}
}

private static ConfidentialClientApplicationBuilder WithCertificateInternal(
this ConfidentialClientApplicationBuilder builder,
CredentialDescription credentialDescription,
IDictionary<string, string>? clientClaims = null)
{
if (clientClaims != null && clientClaims.Count > 0)
{
return builder.WithClientClaims(credentialDescription.Certificate, clientClaims);
}
return builder.WithCertificate(credentialDescription.Certificate);
}

internal /* for test */ async static Task<CredentialDescription?> LoadCredentialForMsalOrFailAsync(
IEnumerable<CredentialDescription> clientCredentials,
ILogger logger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,5 +213,13 @@ internal bool HasClientCredentials
/// Sets query parameters for the query string in the HTTP request to the IdP.
/// </summary>
public IDictionary<string, string>? ExtraQueryParameters { get; set; }

/// <summary>
/// Gets or sets the claims used to create the client assertion for authentication.
/// </summary>
/// <remarks>The client assertion claims are typically used in scenarios where client
/// authentication requires a signed JWT (JSON Web Token). Ensure the claims are properly formatted and encoded
/// as a JSON string before setting this property.</remarks>
public IDictionary<string, string>? ClientAssertionClaims { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.MicrosoftIdentityMessageHandlerOptions() -> void
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.get -> System.Collections.Generic.IList<string!>!
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.set -> void
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.get -> System.Collections.Generic.IDictionary<string!, string!>?
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.set -> void
override Microsoft.Identity.Web.MicrosoftIdentityMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage! request, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage!>!
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.GetAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request) -> Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions?
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.WithAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request, Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions! options) -> System.Net.Http.HttpRequestMessage!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.MicrosoftIdentityMessageHandlerOptions() -> void
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.get -> System.Collections.Generic.IList<string!>!
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.set -> void
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.get -> System.Collections.Generic.IDictionary<string!, string!>?
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.set -> void
override Microsoft.Identity.Web.MicrosoftIdentityMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage! request, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage!>!
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.GetAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request) -> Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions?
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.WithAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request, Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions! options) -> System.Net.Http.HttpRequestMessage!
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
#nullable enable
Microsoft.Identity.Web.TokenAcquisition.GetOrBuildConfidentialClientApplicationAsync(Microsoft.Identity.Web.MergedOptions! mergedOptions, Microsoft.Identity.Web.TokenAcquisitionOptions! tokenAcquisitionOptions) -> System.Threading.Tasks.Task<Microsoft.Identity.Client.IConfidentialClientApplication!>!
static Microsoft.Identity.Web.ConfidentialClientApplicationBuilderExtension.WithClientCredentialsAsync(this Microsoft.Identity.Client.ConfidentialClientApplicationBuilder! builder, System.Collections.Generic.IEnumerable<Microsoft.Identity.Abstractions.CredentialDescription!>! clientCredentials, Microsoft.Extensions.Logging.ILogger! logger, Microsoft.Identity.Abstractions.ICredentialsLoader! credentialsLoader, Microsoft.Identity.Abstractions.CredentialSourceLoaderParameters? credentialSourceLoaderParameters, System.Collections.Generic.IDictionary<string!, string!>? clientClaims = null) -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ConfidentialClientApplicationBuilder!>!
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.MicrosoftIdentityMessageHandlerOptions() -> void
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.get -> System.Collections.Generic.IList<string!>!
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.set -> void
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.get -> System.Collections.Generic.IDictionary<string!, string!>?
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.set -> void
override Microsoft.Identity.Web.MicrosoftIdentityMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage! request, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage!>!
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.GetAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request) -> Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions?
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.WithAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request, Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions! options) -> System.Net.Http.HttpRequestMessage!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.MicrosoftIdentityMessageHandlerOptions() -> void
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.get -> System.Collections.Generic.IList<string!>!
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.set -> void
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.get -> System.Collections.Generic.IDictionary<string!, string!>?
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.set -> void
override Microsoft.Identity.Web.MicrosoftIdentityMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage! request, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage!>!
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.GetAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request) -> Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions?
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.WithAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request, Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions! options) -> System.Net.Http.HttpRequestMessage!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.MicrosoftIdentityMessageHandlerOptions() -> void
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.get -> System.Collections.Generic.IList<string!>!
Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions.Scopes.set -> void
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.get -> System.Collections.Generic.IDictionary<string!, string!>?
Microsoft.Identity.Web.MicrosoftIdentityOptions.ClientAssertionClaims.set -> void
override Microsoft.Identity.Web.MicrosoftIdentityMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage! request, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage!>!
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.GetAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request) -> Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions?
static Microsoft.Identity.Web.HttpRequestMessageAuthenticationExtensions.WithAuthenticationOptions(this System.Net.Http.HttpRequestMessage! request, Microsoft.Identity.Web.MicrosoftIdentityMessageHandlerOptions! options) -> System.Net.Http.HttpRequestMessage!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,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 +258,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 @@ -740,6 +739,7 @@ private MergedOptions GetMergedOptions(string? authenticationScheme, TokenAcquis
Instance = microsoftEntraApplicationOptions.Instance ?? parentMergedOptions.Instance,
AzureRegion = microsoftEntraApplicationOptions.AzureRegion ?? parentMergedOptions.AzureRegion,
TenantId = microsoftEntraApplicationOptions.TenantId ?? parentMergedOptions.TenantId,
ClientAssertionClaims = microsoftEntraApplicationOptions.ClientAssertionClaims ?? parentMergedOptions.ClientAssertionClaims
};
}
else
Expand Down Expand Up @@ -896,9 +896,11 @@ private bool IsInvalidClientCertificateOrSignedAssertionError(MsalServiceExcepti
);
}


#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
Loading