Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
49 changes: 37 additions & 12 deletions src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Extensibility;
using Microsoft.IdentityModel.JsonWebTokens;
Expand All @@ -15,6 +15,7 @@
{
internal static class MsAuth10AtPop
{
// Configure with Certificate
internal static AcquireTokenForClientParameterBuilder WithAtPop(
this AcquireTokenForClientParameterBuilder builder,
X509Certificate2 clientCertificate,
Expand All @@ -28,19 +29,43 @@

builder.WithProofOfPosessionKeyId(popPublicKey);
builder.OnBeforeTokenRequest((data) =>
{
string? signedAssertion = GetSignedClientAssertion(
clientCertificate,
data.RequestUri.AbsoluteUri,
jwkClaim,
clientId,
sendX5C);
{
string? signedAssertion = GetSignedClientAssertion(
clientCertificate,
data.RequestUri.AbsoluteUri,
jwkClaim,
clientId,
sendX5C);

data.BodyParameters.Remove("client_assertion");
data.BodyParameters.Add("request", signedAssertion);

return Task.CompletedTask;
});

return builder;
}

// Configure with Custom Signed Assertion
internal static AcquireTokenForClientParameterBuilder WithAtPop(

Check failure on line 50 in src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs

View workflow job for this annotation

GitHub Actions / Build and run unit tests

Check failure on line 50 in src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs

View workflow job for this annotation

GitHub Actions / Build and run unit tests

Check failure on line 50 in src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs

View workflow job for this annotation

GitHub Actions / Build and run unit tests

Check failure on line 50 in src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs

View workflow job for this annotation

GitHub Actions / Build and run unit tests

Check failure on line 50 in src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs

View workflow job for this annotation

GitHub Actions / Build and run unit tests

Check failure on line 50 in src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs

View workflow job for this annotation

GitHub Actions / Build and run unit tests

Check failure on line 50 in src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs

View workflow job for this annotation

GitHub Actions / Analyse

this AcquireTokenForClientParameterBuilder builder,
CredentialDescription credentialDescription,
string popPublicKey,
string jwkClaim)
{
_ = Throws.IfNull(popPublicKey);
_ = Throws.IfNull(jwkClaim);

data.BodyParameters.Remove("client_assertion");
data.BodyParameters.Add("request", signedAssertion);
builder.WithProofOfPosessionKeyId(popPublicKey);
builder.OnBeforeTokenRequest((data) =>
{
string? signedAssertion = credentialDescription.CachedValue as string;
data.BodyParameters["client_assertion"] = signedAssertion;
data.BodyParameters.Add("req_cnf", Base64UrlEncoder.Encode(jwkClaim));
data.BodyParameters.Add("token_type", "pop");

return Task.CompletedTask;
});
return Task.CompletedTask;
});

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
static Microsoft.Identity.Web.MsAuth10AtPop.WithAtPop(this Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! builder, Microsoft.Identity.Abstractions.CredentialDescription! credentialDescription, string! popPublicKey, string! jwkClaim) -> Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder!
43 changes: 38 additions & 5 deletions src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,11 @@ public async Task<AuthenticationResult> GetAuthenticationResultForAppAsync(
_logger.LogWarning("MSAuth POP configured with pinned certificate. This configuration is being deprecated.");
}

builder.WithAtPop(
application.AppConfig.ClientCredentialCertificate,
tokenAcquisitionOptions.PopPublicKey!,
tokenAcquisitionOptions.PopClaim!,
application.AppConfig.ClientId,
ConfigureAtPopWithCredentials(
builder,
application.AppConfig,
tokenAcquisitionOptions,
mergedOptions.ClientCredentials,
mergedOptions.SendX5C);
}
}
Expand Down Expand Up @@ -629,6 +629,39 @@ public async Task<AuthenticationResult> GetAuthenticationResultForAppAsync(
}
}

private static void ConfigureAtPopWithCredentials(
AcquireTokenForClientParameterBuilder builder,
IAppConfig appConfig,
TokenAcquisitionOptions tokenAcquisitionOptions,
IEnumerable<CredentialDescription>? clientCredentials,
bool sendX5C)
{
// Try to configure AtPop with custom signed assertion first
if (clientCredentials != null)
{
foreach (var credential in clientCredentials)
{
if (credential.SourceType == CredentialSource.CustomSignedAssertion &&
credential.CachedValue != null)
{
builder.WithAtPop(
credential,
tokenAcquisitionOptions.PopPublicKey!,
tokenAcquisitionOptions.PopClaim!);
return;
}
}
}

// Fall back to certificate-based AtPop configuration
builder.WithAtPop(
appConfig.ClientCredentialCertificate,
tokenAcquisitionOptions.PopPublicKey!,
tokenAcquisitionOptions.PopClaim!,
appConfig.ClientId,
sendX5C);
}

/// <summary>
/// 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.
Expand Down
14 changes: 7 additions & 7 deletions tests/DevApps/aspnet-mvc/OwinWebApi/Web.config
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.3.1.0" newVersion="8.3.1.0"/>
<bindingRedirect oldVersion="0.0.0.0-8.5.0.0" newVersion="8.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.2" newVersion="6.0.0.2"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
Expand All @@ -74,27 +74,27 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Tokens" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.3.1.0" newVersion="8.3.1.0"/>
<bindingRedirect oldVersion="0.0.0.0-8.5.0.0" newVersion="8.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocols.WsFederation" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocols.OpenIdConnect" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.3.1.0" newVersion="8.3.1.0"/>
<bindingRedirect oldVersion="0.0.0.0-8.5.0.0" newVersion="8.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocols" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.3.1.0" newVersion="8.3.1.0"/>
<bindingRedirect oldVersion="0.0.0.0-8.5.0.0" newVersion="8.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Logging" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.3.1.0" newVersion="8.3.1.0"/>
<bindingRedirect oldVersion="0.0.0.0-8.5.0.0" newVersion="8.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Abstractions" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.3.1.0" newVersion="8.3.1.0"/>
<bindingRedirect oldVersion="0.0.0.0-8.5.0.0" newVersion="8.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0A613F4DD989E8AE" culture="neutral"/>
Expand Down
6 changes: 3 additions & 3 deletions tests/Microsoft.Identity.Web.Test/MsAuth10AtPopTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ public async Task MsAuth10AtPop_WithAtPop_ShouldPopulateBuilderWithProofOfPosess

// Assert
httpTokenRequest.ActualRequestPostData.TryGetValue("request", out string? request);
Assert.NotNull(request);
Assert.Null(request);
httpTokenRequest.ActualRequestPostData.TryGetValue("client_assertion", out string? clientAssertion);
Assert.Null(clientAssertion);
Assert.NotNull(clientAssertion);

JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
JwtSecurityToken assertion = jwtSecurityTokenHandler.ReadJwtToken(request);
JwtSecurityToken assertion = jwtSecurityTokenHandler.ReadJwtToken(clientAssertion);

Assert.Equal("https://login.microsoftonline.com/common/oauth2/v2.0/token", assertion.Claims.Single(c => c.Type == "aud").Value);
Assert.Equal(TestConstants.ClientId, assertion.Claims.Single(c => c.Type == "iss").Value);
Expand Down
Loading