diff --git a/Directory.Build.props b/Directory.Build.props index 14db851ce..44087f21a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -86,8 +86,8 @@ - 8.6.1 - 4.69.1 + 8.7.0 + 4.70.0 3.3.0 4.7.2 4.6.0 @@ -95,7 +95,6 @@ 4.6.0 4.36.0 4.57.0-preview - 3.1.3 8.2.0 8.0.5 @@ -173,6 +172,7 @@ 6.0.2 6.0.0 + 3.1.3 6.0.0 7.0.2 6.0.1 @@ -196,6 +196,7 @@ 4.7.1 2.1.0 2.1.1 + 3.1.3 2.1.0 2.1.0 2.2.4 diff --git a/changelog.md b/changelog.md index a15db3ae8..7483ede34 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,11 @@ +3.8.1 +======== +### New features +- Updated to Microsoft.IdentityModel.* [8.7.0](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases/tag/8.7.0) + +### Bug fixes +- Pins Microsoft.Extensions.Http dependency version to 3.1.3 for .NET Framework and .NET Standard and uses inbox version for .NET Core. See [#3145](https://github.com/AzureAD/microsoft-identity-web/issues/3145). + 3.8.0 ======== ### New feature diff --git a/src/Microsoft.Identity.Web.OWIN/Microsoft.Identity.Web.OWIN.csproj b/src/Microsoft.Identity.Web.OWIN/Microsoft.Identity.Web.OWIN.csproj index 25dfd23c7..612cff1d7 100644 --- a/src/Microsoft.Identity.Web.OWIN/Microsoft.Identity.Web.OWIN.csproj +++ b/src/Microsoft.Identity.Web.OWIN/Microsoft.Identity.Web.OWIN.csproj @@ -29,7 +29,6 @@ - @@ -40,6 +39,10 @@ + + + + diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/AtPopOperation.cs b/src/Microsoft.Identity.Web.TokenAcquisition/AtPopOperation.cs new file mode 100644 index 000000000..bfa4a7a11 --- /dev/null +++ b/src/Microsoft.Identity.Web.TokenAcquisition/AtPopOperation.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using Microsoft.Identity.Client.AuthScheme; +using Microsoft.Identity.Client; +using Microsoft.IdentityModel.Tokens; + +namespace Microsoft.Identity.Web +{ + internal class AtPopOperation : IAuthenticationOperation + { + private readonly string _reqCnf; + + public AtPopOperation(string keyId, string reqCnf) + { + KeyId = keyId; + _reqCnf = reqCnf; + } + + public int TelemetryTokenType => 4; // as per TelemetryTokenTypeConstants + + public string AuthorizationHeaderPrefix => "Bearer"; // these tokens go over bearer + + public string KeyId { get; } + + public string AccessTokenType => "pop"; // eSTS returns token_type=pop and MSAL needs to know + + public void FormatResult(AuthenticationResult authenticationResult) + { + // no-op, adding the SHR is done by the caller + } + + public IReadOnlyDictionary GetTokenRequestParams() + { + return new Dictionary() + { + {"req_cnf", Base64UrlEncoder.Encode(_reqCnf) }, + {"token_type", "pop" } + }; + } + } +} diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/Microsoft.Identity.Web.TokenAcquisition.csproj b/src/Microsoft.Identity.Web.TokenAcquisition/Microsoft.Identity.Web.TokenAcquisition.csproj index 1a5956163..51b1aa9e7 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/Microsoft.Identity.Web.TokenAcquisition.csproj +++ b/src/Microsoft.Identity.Web.TokenAcquisition/Microsoft.Identity.Web.TokenAcquisition.csproj @@ -35,10 +35,13 @@ - + + + + diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs b/src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs index dee57e616..d255f776f 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs @@ -1,15 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.Collections.Generic; -using System.IdentityModel.Tokens.Jwt; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; using Microsoft.Identity.Client; using Microsoft.Identity.Client.Extensibility; -using Microsoft.IdentityModel.JsonWebTokens; -using Microsoft.IdentityModel.Tokens; namespace Microsoft.Identity.Web { @@ -17,69 +10,18 @@ internal static class MsAuth10AtPop { internal static AcquireTokenForClientParameterBuilder WithAtPop( this AcquireTokenForClientParameterBuilder builder, - X509Certificate2 clientCertificate, string popPublicKey, - string jwkClaim, - string clientId, - bool sendX5C) + string jwkClaim) { - _ = Throws.IfNull(popPublicKey); - _ = Throws.IfNull(jwkClaim); + _ = Throws.IfNullOrWhitespace(popPublicKey); + _ = Throws.IfNullOrWhitespace(jwkClaim); - builder.WithProofOfPosessionKeyId(popPublicKey); - builder.OnBeforeTokenRequest((data) => - { - 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; - } - - private static string? GetSignedClientAssertion( - X509Certificate2 certificate, - string audience, - string jwkClaim, - string clientId, - bool sendX5C) - { - // no need to add exp, nbf as JsonWebTokenHandler will add them by default - var claims = new Dictionary() - { - { "aud", audience }, - { "iss", clientId }, - { "jti", Guid.NewGuid().ToString() }, - { "sub", clientId }, - { "pop_jwk", jwkClaim } - }; - - var signingCredentials = new X509SigningCredentials(certificate); - var securityTokenDescriptor = new SecurityTokenDescriptor - { - Claims = claims, - SigningCredentials = signingCredentials - }; - - if (sendX5C) + AtPopOperation op = new AtPopOperation(popPublicKey, jwkClaim); + builder.WithAuthenticationExtension(new MsalAuthenticationExtension() { - string x5cValue = Convert.ToBase64String(certificate.GetRawCertData()); - securityTokenDescriptor.AdditionalHeaderClaims = - new Dictionary() { { "x5c", new List { x5cValue } } }; - } - - JsonWebTokenHandler tokenHandler = new JsonWebTokenHandler(); - string token = tokenHandler.CreateToken(securityTokenDescriptor); - - return token; + AuthenticationOperation = op + }); + return builder; } } } diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt index e69de29bb..9d7f2e5ab 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net462/InternalAPI.Unshipped.txt @@ -0,0 +1,9 @@ +Microsoft.Identity.Web.AtPopOperation +Microsoft.Identity.Web.AtPopOperation.AccessTokenType.get -> string! +Microsoft.Identity.Web.AtPopOperation.AtPopOperation(string! keyId, string! reqCnf) -> void +Microsoft.Identity.Web.AtPopOperation.AuthorizationHeaderPrefix.get -> string! +Microsoft.Identity.Web.AtPopOperation.FormatResult(Microsoft.Identity.Client.AuthenticationResult! authenticationResult) -> void +Microsoft.Identity.Web.AtPopOperation.GetTokenRequestParams() -> System.Collections.Generic.IReadOnlyDictionary! +Microsoft.Identity.Web.AtPopOperation.KeyId.get -> string! +Microsoft.Identity.Web.AtPopOperation.TelemetryTokenType.get -> int +static Microsoft.Identity.Web.MsAuth10AtPop.WithAtPop(this Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! builder, string! popPublicKey, string! jwkClaim) -> Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt index e69de29bb..9d7f2e5ab 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net472/InternalAPI.Unshipped.txt @@ -0,0 +1,9 @@ +Microsoft.Identity.Web.AtPopOperation +Microsoft.Identity.Web.AtPopOperation.AccessTokenType.get -> string! +Microsoft.Identity.Web.AtPopOperation.AtPopOperation(string! keyId, string! reqCnf) -> void +Microsoft.Identity.Web.AtPopOperation.AuthorizationHeaderPrefix.get -> string! +Microsoft.Identity.Web.AtPopOperation.FormatResult(Microsoft.Identity.Client.AuthenticationResult! authenticationResult) -> void +Microsoft.Identity.Web.AtPopOperation.GetTokenRequestParams() -> System.Collections.Generic.IReadOnlyDictionary! +Microsoft.Identity.Web.AtPopOperation.KeyId.get -> string! +Microsoft.Identity.Web.AtPopOperation.TelemetryTokenType.get -> int +static Microsoft.Identity.Web.MsAuth10AtPop.WithAtPop(this Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! builder, string! popPublicKey, string! jwkClaim) -> Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net6.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net6.0/InternalAPI.Unshipped.txt index e69de29bb..9d7f2e5ab 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net6.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net6.0/InternalAPI.Unshipped.txt @@ -0,0 +1,9 @@ +Microsoft.Identity.Web.AtPopOperation +Microsoft.Identity.Web.AtPopOperation.AccessTokenType.get -> string! +Microsoft.Identity.Web.AtPopOperation.AtPopOperation(string! keyId, string! reqCnf) -> void +Microsoft.Identity.Web.AtPopOperation.AuthorizationHeaderPrefix.get -> string! +Microsoft.Identity.Web.AtPopOperation.FormatResult(Microsoft.Identity.Client.AuthenticationResult! authenticationResult) -> void +Microsoft.Identity.Web.AtPopOperation.GetTokenRequestParams() -> System.Collections.Generic.IReadOnlyDictionary! +Microsoft.Identity.Web.AtPopOperation.KeyId.get -> string! +Microsoft.Identity.Web.AtPopOperation.TelemetryTokenType.get -> int +static Microsoft.Identity.Web.MsAuth10AtPop.WithAtPop(this Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! builder, string! popPublicKey, string! jwkClaim) -> Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net7.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net7.0/InternalAPI.Unshipped.txt index e69de29bb..9d7f2e5ab 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net7.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net7.0/InternalAPI.Unshipped.txt @@ -0,0 +1,9 @@ +Microsoft.Identity.Web.AtPopOperation +Microsoft.Identity.Web.AtPopOperation.AccessTokenType.get -> string! +Microsoft.Identity.Web.AtPopOperation.AtPopOperation(string! keyId, string! reqCnf) -> void +Microsoft.Identity.Web.AtPopOperation.AuthorizationHeaderPrefix.get -> string! +Microsoft.Identity.Web.AtPopOperation.FormatResult(Microsoft.Identity.Client.AuthenticationResult! authenticationResult) -> void +Microsoft.Identity.Web.AtPopOperation.GetTokenRequestParams() -> System.Collections.Generic.IReadOnlyDictionary! +Microsoft.Identity.Web.AtPopOperation.KeyId.get -> string! +Microsoft.Identity.Web.AtPopOperation.TelemetryTokenType.get -> int +static Microsoft.Identity.Web.MsAuth10AtPop.WithAtPop(this Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! builder, string! popPublicKey, string! jwkClaim) -> Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/InternalAPI.Unshipped.txt index e69de29bb..9d7f2e5ab 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net8.0/InternalAPI.Unshipped.txt @@ -0,0 +1,9 @@ +Microsoft.Identity.Web.AtPopOperation +Microsoft.Identity.Web.AtPopOperation.AccessTokenType.get -> string! +Microsoft.Identity.Web.AtPopOperation.AtPopOperation(string! keyId, string! reqCnf) -> void +Microsoft.Identity.Web.AtPopOperation.AuthorizationHeaderPrefix.get -> string! +Microsoft.Identity.Web.AtPopOperation.FormatResult(Microsoft.Identity.Client.AuthenticationResult! authenticationResult) -> void +Microsoft.Identity.Web.AtPopOperation.GetTokenRequestParams() -> System.Collections.Generic.IReadOnlyDictionary! +Microsoft.Identity.Web.AtPopOperation.KeyId.get -> string! +Microsoft.Identity.Web.AtPopOperation.TelemetryTokenType.get -> int +static Microsoft.Identity.Web.MsAuth10AtPop.WithAtPop(this Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! builder, string! popPublicKey, string! jwkClaim) -> Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/InternalAPI.Unshipped.txt index e69de29bb..9d7f2e5ab 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/net9.0/InternalAPI.Unshipped.txt @@ -0,0 +1,9 @@ +Microsoft.Identity.Web.AtPopOperation +Microsoft.Identity.Web.AtPopOperation.AccessTokenType.get -> string! +Microsoft.Identity.Web.AtPopOperation.AtPopOperation(string! keyId, string! reqCnf) -> void +Microsoft.Identity.Web.AtPopOperation.AuthorizationHeaderPrefix.get -> string! +Microsoft.Identity.Web.AtPopOperation.FormatResult(Microsoft.Identity.Client.AuthenticationResult! authenticationResult) -> void +Microsoft.Identity.Web.AtPopOperation.GetTokenRequestParams() -> System.Collections.Generic.IReadOnlyDictionary! +Microsoft.Identity.Web.AtPopOperation.KeyId.get -> string! +Microsoft.Identity.Web.AtPopOperation.TelemetryTokenType.get -> int +static Microsoft.Identity.Web.MsAuth10AtPop.WithAtPop(this Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! builder, string! popPublicKey, string! jwkClaim) -> Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt index e69de29bb..9d7f2e5ab 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Web.TokenAcquisition/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt @@ -0,0 +1,9 @@ +Microsoft.Identity.Web.AtPopOperation +Microsoft.Identity.Web.AtPopOperation.AccessTokenType.get -> string! +Microsoft.Identity.Web.AtPopOperation.AtPopOperation(string! keyId, string! reqCnf) -> void +Microsoft.Identity.Web.AtPopOperation.AuthorizationHeaderPrefix.get -> string! +Microsoft.Identity.Web.AtPopOperation.FormatResult(Microsoft.Identity.Client.AuthenticationResult! authenticationResult) -> void +Microsoft.Identity.Web.AtPopOperation.GetTokenRequestParams() -> System.Collections.Generic.IReadOnlyDictionary! +Microsoft.Identity.Web.AtPopOperation.KeyId.get -> string! +Microsoft.Identity.Web.AtPopOperation.TelemetryTokenType.get -> int +static Microsoft.Identity.Web.MsAuth10AtPop.WithAtPop(this Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! builder, string! popPublicKey, string! jwkClaim) -> Microsoft.Identity.Client.AcquireTokenForClientParameterBuilder! diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs index 7256363d4..340c5b922 100644 --- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs @@ -589,11 +589,8 @@ public async Task GetAuthenticationResultForAppAsync( } builder.WithAtPop( - application.AppConfig.ClientCredentialCertificate, - tokenAcquisitionOptions.PopPublicKey!, - tokenAcquisitionOptions.PopClaim!, - application.AppConfig.ClientId, - mergedOptions.SendX5C); + tokenAcquisitionOptions.PopPublicKey!, + tokenAcquisitionOptions.PopClaim!); } } } diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj index 0642d4726..7408da953 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj @@ -25,11 +25,14 @@ - - + + + + + diff --git a/tests/DevApps/aspnet-mvc/OwinWebApi/Web.config b/tests/DevApps/aspnet-mvc/OwinWebApi/Web.config index 2d99d4971..4c9a36187 100644 --- a/tests/DevApps/aspnet-mvc/OwinWebApi/Web.config +++ b/tests/DevApps/aspnet-mvc/OwinWebApi/Web.config @@ -58,11 +58,11 @@ - + - + @@ -74,7 +74,7 @@ - + @@ -82,19 +82,19 @@ - + - + - + - + diff --git a/tests/Microsoft.Identity.Web.Test.Common/Mocks/MockHttpCreator.cs b/tests/Microsoft.Identity.Web.Test.Common/Mocks/MockHttpCreator.cs index e3759c223..19918c8d3 100644 --- a/tests/Microsoft.Identity.Web.Test.Common/Mocks/MockHttpCreator.cs +++ b/tests/Microsoft.Identity.Web.Test.Common/Mocks/MockHttpCreator.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Http; @@ -11,10 +10,13 @@ namespace Microsoft.Identity.Web.Test.Common.Mocks { public static class MockHttpCreator { - private static HttpResponseMessage CreateSuccessfulClientCredentialTokenResponseMessage(string token = "header.payload.signature", int expiry = 3599) + private static HttpResponseMessage CreateSuccessfulClientCredentialTokenResponseMessage( + string token = "header.payload.signature", + string tokenType = "Bearer", + int expiry = 3599) { return CreateSuccessResponseMessage( - "{\"token_type\":\"Bearer\",\"expires_in\":" + expiry + ",\"client_info\":\"" + CreateClientInfo() + "\",\"access_token\":\"" + token + "\"}"); + "{\"token_type\":\"" + tokenType + "\",\"expires_in\":" + expiry + ",\"client_info\":\"" + CreateClientInfo() + "\",\"access_token\":\"" + token + "\"}"); } public static HttpResponseMessage CreateSuccessResponseMessage(string successResponse) @@ -47,12 +49,12 @@ public static MockHttpMessageHandler CreateInstanceDiscoveryMockHandler( } public static MockHttpMessageHandler CreateClientCredentialTokenHandler( - string token = "header.payload.signature", int expiresIn = 3599) + string token = "header.payload.signature", string tokenType = "Bearer", int expiresIn = 3599) { var handler = new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, - ResponseMessage = CreateSuccessfulClientCredentialTokenResponseMessage(token, expiresIn), + ResponseMessage = CreateSuccessfulClientCredentialTokenResponseMessage(token, tokenType, expiresIn), }; return handler; diff --git a/tests/Microsoft.Identity.Web.Test/AtPopOperationTests.cs b/tests/Microsoft.Identity.Web.Test/AtPopOperationTests.cs new file mode 100644 index 000000000..3f9c17aea --- /dev/null +++ b/tests/Microsoft.Identity.Web.Test/AtPopOperationTests.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.IdentityModel.Tokens; +using Xunit; + +namespace Microsoft.Identity.Web.Test +{ + public class AtPopOperationTests + { + [Fact] + public void Constructor_InitializesProperties() + { + // Arrange + string keyId = "testKeyId"; + string reqCnf = "testReqCnf"; + + // Act + var atPopOperation = new AtPopOperation(keyId, reqCnf); + + // Assert + Assert.Equal(keyId, atPopOperation.KeyId); + Assert.Equal(4, atPopOperation.TelemetryTokenType); + Assert.Equal("Bearer", atPopOperation.AuthorizationHeaderPrefix); + Assert.Equal("pop", atPopOperation.AccessTokenType); + } + + [Fact] + public void GetTokenRequestParams_ReturnsCorrectDictionary() + { + // Arrange + string reqCnf = "testReqCnf"; + var atPopOperation = new AtPopOperation("testKeyId", reqCnf); + + // Act + var tokenRequestParams = atPopOperation.GetTokenRequestParams(); + + // Assert + Assert.Equal(2, tokenRequestParams.Count); + Assert.Equal(Base64UrlEncoder.Encode(reqCnf), tokenRequestParams["req_cnf"]); + Assert.Equal("pop", tokenRequestParams["token_type"]); + } + } +} diff --git a/tests/Microsoft.Identity.Web.Test/MsAuth10AtPopTests.cs b/tests/Microsoft.Identity.Web.Test/MsAuth10AtPopTests.cs index 85757a5e1..4649659d4 100644 --- a/tests/Microsoft.Identity.Web.Test/MsAuth10AtPopTests.cs +++ b/tests/Microsoft.Identity.Web.Test/MsAuth10AtPopTests.cs @@ -2,15 +2,13 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; -using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; -using Microsoft.Graph; using Microsoft.Identity.Client; using Microsoft.Identity.Web.Test.Common; using Microsoft.Identity.Web.Test.Common.Mocks; +using Microsoft.IdentityModel.Tokens; using Xunit; namespace Microsoft.Identity.Web.Test @@ -22,7 +20,7 @@ public async Task MsAuth10AtPop_WithAtPop_ShouldPopulateBuilderWithProofOfPosess { // Arrange using MockHttpClientFactory mockHttpClientFactory = new MockHttpClientFactory(); - using var httpTokenRequest = MockHttpCreator.CreateClientCredentialTokenHandler(); + using var httpTokenRequest = MockHttpCreator.CreateClientCredentialTokenHandler(tokenType: "pop"); mockHttpClientFactory.AddMockHandler(httpTokenRequest); var certificateDescription = CertificateDescription.FromBase64Encoded( @@ -44,31 +42,33 @@ public async Task MsAuth10AtPop_WithAtPop_ShouldPopulateBuilderWithProofOfPosess // Act AuthenticationResult result = await app.AcquireTokenForClient(new[] { TestConstants.Scopes }) - .WithAtPop(certificateDescription.Certificate, popPublicKey, jwkClaim, TestConstants.ClientId, true) + .WithAtPop(popPublicKey, jwkClaim) .ExecuteAsync(); // 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); + + // jwk is now passed in the http request as req_cnf + httpTokenRequest.ActualRequestPostData.TryGetValue("req_cnf", out string? reqCnf); + Assert.Equal(Base64UrlEncoder.Encode(jwkClaim), reqCnf); + + httpTokenRequest.ActualRequestPostData.TryGetValue("token_type", out string? tokenType); + Assert.Equal("pop", tokenType); 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); Assert.Equal(TestConstants.ClientId, assertion.Claims.Single(c => c.Type == "sub").Value); Assert.NotEmpty(assertion.Claims.Single(c => c.Type == "jti").Value); - Assert.Equal(jwkClaim, assertion.Claims.Single(c => c.Type == "pop_jwk").Value); - - assertion.Header.TryGetValue("x5c", out var x5cClaimValue); - Assert.NotNull(x5cClaimValue); - string actualX5c = (string)((List)x5cClaimValue).Single(); - string expectedX5C= Convert.ToBase64String(certificateDescription.Certificate.RawData); - - Assert.Equal(expectedX5C, actualX5c); + // clientAssertion will no longer contain jwk + Assert.Null(assertion.Claims.SingleOrDefault(c => c.Type == "pop_jwk")); } [Fact] @@ -76,20 +76,13 @@ public void MsAuth10AtPop_ThrowsWithNullPopKeyTest() { // Arrange IConfidentialClientApplication app = CreateBuilder(); -#pragma warning disable SYSLIB0057 // Type or member is obsolete - using X509Certificate2 clientCertificate = new([]); -#pragma warning restore SYSLIB0057 // Type or member is obsolete var jwkClaim = "jwk_claim"; - var clientId = "client_id"; // Act & Assert - Assert.Throws(() => MsAuth10AtPop.WithAtPop( - app.AcquireTokenForClient(new[] { TestConstants.Scopes }), - clientCertificate, + Assert.Throws(() => MsAuth10AtPop.WithAtPop( + app.AcquireTokenForClient([TestConstants.Scopes]), string.Empty, - jwkClaim, - clientId, - true)); + jwkClaim)); } [Fact] @@ -97,17 +90,13 @@ public void MsAuth10AtPop_ThrowsWithNullJwkClaimTest() { // Arrange IConfidentialClientApplication app = CreateBuilder(); -#pragma warning disable SYSLIB0057 // Type or member is obsolete - using X509Certificate2 clientCertificate = new([]); -#pragma warning restore SYSLIB0057 // Type or member is obsolete var popPublicKey = "pop_key"; - var clientId = "client_id"; // Act & Assert #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => MsAuth10AtPop.WithAtPop( app.AcquireTokenForClient(new[] { TestConstants.Scopes }), - clientCertificate, popPublicKey, null, clientId, true)); + popPublicKey, null)); #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. }