Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
42 changes: 42 additions & 0 deletions src/Microsoft.Identity.Web.TokenAcquisition/AtPopOperation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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<string, string> GetTokenRequestParams()
{
return new Dictionary<string, string>()
{
{"req_cnf", Base64UrlEncoder.Encode(_reqCnf) },
{"token_type", "pop" }
};
}
}
}
74 changes: 8 additions & 66 deletions src/Microsoft.Identity.Web.TokenAcquisition/MsAuth10AtPop.cs
Original file line number Diff line number Diff line change
@@ -1,85 +1,27 @@
// 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
{
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<string, object>()
{
{ "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<string, object>() { { "x5c", new List<string> { x5cValue } } };
}

JsonWebTokenHandler tokenHandler = new JsonWebTokenHandler();
string token = tokenHandler.CreateToken(securityTokenDescriptor);

return token;
AuthenticationOperation = op
});
return builder;
}
}
}
Original file line number Diff line number Diff line change
@@ -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<string!, string!>!
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!
Original file line number Diff line number Diff line change
@@ -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<string!, string!>!
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!
Original file line number Diff line number Diff line change
@@ -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<string!, string!>!
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!
Original file line number Diff line number Diff line change
@@ -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<string!, string!>!
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!
Original file line number Diff line number Diff line change
@@ -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<string!, string!>!
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!
Original file line number Diff line number Diff line change
@@ -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<string!, string!>!
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!
Original file line number Diff line number Diff line change
@@ -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<string!, string!>!
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!
Original file line number Diff line number Diff line change
Expand Up @@ -589,11 +589,8 @@ public async Task<AuthenticationResult> GetAuthenticationResultForAppAsync(
}

builder.WithAtPop(
application.AppConfig.ClientCredentialCertificate,
tokenAcquisitionOptions.PopPublicKey!,
tokenAcquisitionOptions.PopClaim!,
application.AppConfig.ClientId,
mergedOptions.SendX5C);
tokenAcquisitionOptions.PopPublicKey!,
tokenAcquisitionOptions.PopClaim!);
}
}
}
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
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
Loading
Loading