Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding authentication extension api to enable the extending of MSAL #4859

Merged
merged 61 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
a91db53
Initial commit
Jul 17, 2024
e9de87c
Updating Core logic for CDT
Jul 23, 2024
0806403
Updates
Jul 23, 2024
3a6eb43
Merge branch 'main' into trwalke/CDTPrototype
Aug 28, 2024
0fa6692
Refactoring CdtAuthScheme
Sep 3, 2024
c4c55d4
Adding cache test case
Sep 3, 2024
21f7fe2
Resolving issues
Sep 4, 2024
317c090
Update
Sep 5, 2024
e75ba49
Adding api to enable additional caching parameters
Sep 6, 2024
40c6b5d
clean up
Sep 6, 2024
8558e6e
Clean up, Refactoring, Updating tests
Sep 9, 2024
226d060
Fixing test issue
Sep 10, 2024
9862f3a
Resolving build issue
Sep 10, 2024
0ab2c7f
Test fix
Sep 10, 2024
64b8b92
Refactoring CDT logic to make it extensible
Sep 11, 2024
1c14eee
hooking up addin
Sep 11, 2024
17fd857
Merge branch 'main' into trwalke/CDTPrototype
trwalke Sep 11, 2024
dee4c5f
Adding support for arrays and objects
Sep 11, 2024
646a9fc
Merge branch 'main' into trwalke/AdditionalCacheParams
trwalke Sep 11, 2024
b59b25d
Merge branch 'trwalke/AdditionalCacheParams' into trwalke/CDTPrototype
Sep 11, 2024
9e78a10
Hooking up Additional cache param logic
Sep 11, 2024
468354e
Clean up
Sep 11, 2024
a89226c
Adding integration test
Sep 24, 2024
3f96e48
Merge branch 'main' into trwalke/CDTPrototype
Sep 24, 2024
6a88251
Fixing tests
Sep 24, 2024
29abebf
Ignoring test
Sep 24, 2024
3feb745
Resolving build error
Sep 24, 2024
59ec5c1
Making constraints an array
Sep 24, 2024
27f3791
Updating CDT format
Sep 24, 2024
543915a
Moving CDT implementation to new project.
Sep 30, 2024
78ad414
clean up
Sep 30, 2024
8d13e91
Moving cdt implementation to new project. Removing MSAL internal depe…
Sep 30, 2024
9a06262
Setting tokenType to internal
Sep 30, 2024
70b972b
Resolving build issues
Sep 30, 2024
642c2cf
Refactoring CdtAuthScheme to use wilson
Oct 1, 2024
68a8922
Resolving build errors
Oct 1, 2024
3fba7ba
Revert "Resolving build errors"
Oct 1, 2024
75e9955
Fixing error
Oct 1, 2024
a3b4375
Revert "Fixing error"
Oct 1, 2024
9abb9bc
Revert "Revert "Resolving build errors""
Oct 1, 2024
ffbe6e3
Revert "Resolving build errors"
Oct 1, 2024
aadc700
Renaming authentication extension apis
Oct 2, 2024
54fb683
Removing CDT
Oct 2, 2024
f347e2b
Ignoring failing test
trwalke Oct 2, 2024
fba6bd9
Revert "Removing CDT"
Oct 2, 2024
a069466
Updating naming
Oct 2, 2024
2a96823
Revert "Revert "Removing CDT""
Oct 2, 2024
fc79c2a
Update Microsoft.Identity.Client.csproj
trwalke Oct 2, 2024
ab14305
Revert "Revert "Revert "Removing CDT"""
Oct 4, 2024
4f046ed
Merge branch 'main' into trwalke/CDTPrototype
Oct 14, 2024
f8ed03e
Revert "Revert "Revert "Revert "Removing CDT""""
Oct 14, 2024
c46d116
Refactoring.
Oct 15, 2024
d07a48b
Additional test cases
Oct 16, 2024
c3ad58a
Clean up
Oct 16, 2024
ec36b35
Refactoring
Oct 16, 2024
ca3f3d0
Enabling CdtTelemetry
Oct 11, 2024
c2cba7e
Renaming
Oct 17, 2024
c8ff19f
TestFix
Oct 17, 2024
4b92a55
Apply suggestions from code review
trwalke Oct 17, 2024
b69b240
Adding test
Oct 17, 2024
0ea1075
Fixing test issue
Oct 17, 2024
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 @@ -334,9 +334,10 @@ public T WithB2CAuthority(string authorityUri)
return this as T;
}

internal /* for testing */ T WithAuthenticationScheme(IAuthenticationScheme scheme)
internal /* for testing */ T WithAuthenticationOperation(IAuthenticationOperation authOperation)
{
CommonParameters.AuthenticationScheme = scheme ?? throw new ArgumentNullException(nameof(scheme));
ValidateUseOfExperimentalFeature();
CommonParameters.AuthenticationOperation = authOperation ?? throw new ArgumentNullException(nameof(authOperation));
return this as T;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client.ApiConfig;
using Microsoft.Identity.Client.ApiConfig.Executors;
using Microsoft.Identity.Client.AppConfig;
using Microsoft.Identity.Client.AuthScheme.PoP;
Expand Down Expand Up @@ -82,7 +85,7 @@ public T WithProofOfPossession(PoPAuthenticationConfiguration popAuthenticationC

CommonParameters.PopAuthenticationConfiguration = popAuthenticationConfiguration ?? throw new ArgumentNullException(nameof(popAuthenticationConfiguration));

CommonParameters.AuthenticationScheme = new PopAuthenticationScheme(CommonParameters.PopAuthenticationConfiguration, ServiceBundle);
CommonParameters.AuthenticationOperation = new PopAuthenticationOperation(CommonParameters.PopAuthenticationConfiguration, ServiceBundle);

return this as T;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public AcquireTokenByUsernamePasswordParameterBuilder WithProofOfPossession(stri
popConfig.HttpMethod = httpMethod;

CommonParameters.PopAuthenticationConfiguration = popConfig;
CommonParameters.AuthenticationScheme = new PopBrokerAuthenticationScheme();
CommonParameters.AuthenticationOperation = new PopBrokerAuthenticationOperation();

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ public AcquireTokenInteractiveParameterBuilder WithProofOfPossession(string nonc
popConfig.HttpMethod = httpMethod;

CommonParameters.PopAuthenticationConfiguration = popConfig;
CommonParameters.AuthenticationScheme = new PopBrokerAuthenticationScheme();
CommonParameters.AuthenticationOperation = new PopBrokerAuthenticationOperation();

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public AcquireTokenSilentParameterBuilder WithProofOfPossession(PoPAuthenticatio

CommonParameters.PopAuthenticationConfiguration = popAuthenticationConfiguration ?? throw new ArgumentNullException(nameof(popAuthenticationConfiguration));

CommonParameters.AuthenticationScheme = new PopAuthenticationScheme(CommonParameters.PopAuthenticationConfiguration, ServiceBundle);
CommonParameters.AuthenticationOperation = new PopAuthenticationOperation(CommonParameters.PopAuthenticationConfiguration, ServiceBundle);

return this;
}
Expand Down Expand Up @@ -232,20 +232,20 @@ public AcquireTokenSilentParameterBuilder WithProofOfPossession(string nonce, Ht
popConfig.HttpMethod = httpMethod ?? throw new ArgumentNullException(nameof(httpMethod));
popConfig.Nonce = nonce;

IAuthenticationScheme authenticationScheme;
IAuthenticationOperation authenticationScheme;

//POP Auth scheme should not wrap and sign token when broker is enabled for public clients
if (ServiceBundle.Config.IsBrokerEnabled)
{
popConfig.SignHttpRequest = false;
authenticationScheme = new PopBrokerAuthenticationScheme();
authenticationScheme = new PopBrokerAuthenticationOperation();
}
else
{
authenticationScheme = new PopAuthenticationScheme(popConfig, ServiceBundle);
authenticationScheme = new PopAuthenticationOperation(popConfig, ServiceBundle);
}
CommonParameters.PopAuthenticationConfiguration = popConfig;
CommonParameters.AuthenticationScheme = authenticationScheme;
CommonParameters.AuthenticationOperation = authenticationScheme;

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal class AcquireTokenCommonParameters
public IDictionary<string, string> ExtraQueryParameters { get; set; }
public string Claims { get; set; }
public AuthorityInfo AuthorityOverride { get; set; }
public IAuthenticationScheme AuthenticationScheme { get; set; } = new BearerAuthenticationScheme();
public IAuthenticationOperation AuthenticationOperation { get; set; } = new BearerAuthenticationOperation();
public IDictionary<string, string> ExtraHttpHeaders { get; set; }
public PoPAuthenticationConfiguration PopAuthenticationConfiguration { get; set; }
public Func<OnBeforeTokenRequestData, Task> OnBeforeTokenRequestHandler { get; internal set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ public static bool StoreTokenTypeInCacheKey(string tokenType)
{
if (string.Equals(
tokenType,
BearerAuthenticationScheme.BearerTokenType,
BearerAuthenticationOperation.BearerTokenType,
StringComparison.OrdinalIgnoreCase))
{
return false;
}

if (string.Equals(
tokenType,
SSHCertAuthenticationScheme.SSHCertTokenType,
SSHCertAuthenticationOperation.SSHCertTokenType,
StringComparison.OrdinalIgnoreCase))
{
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@

namespace Microsoft.Identity.Client.AuthScheme.Bearer
{
internal class BearerAuthenticationScheme : IAuthenticationScheme
internal class BearerAuthenticationOperation : IAuthenticationOperation
{
internal const string BearerTokenType = "bearer";

public TokenType TelemetryTokenType => TokenType.Bearer;
public int TelemetryTokenType => (int)TokenType.Bearer;

public string AuthorizationHeaderPrefix => "Bearer";

public string AccessTokenType => BearerTokenType;

public string KeyId => null;

public string FormatAccessToken(MsalAccessTokenCacheItem msalAccessTokenCacheItem)
public void FormatResult(AuthenticationResult authenticationResult)
trwalke marked this conversation as resolved.
Show resolved Hide resolved
{
return msalAccessTokenCacheItem.Secret;
// no-op
}

public IReadOnlyDictionary<string, string> GetTokenRequestParams()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,28 @@ namespace Microsoft.Identity.Client.AuthScheme
/// <summary>
/// Used to modify the experience depending on the type of token asked.
/// </summary>
internal interface IAuthenticationScheme
public interface IAuthenticationOperation
{
/// <summary>
/// Value to log to telemetry to indicate pop usage.
/// Value to log to telemetry
/// Values available:
trwalke marked this conversation as resolved.
Show resolved Hide resolved
///
/// Bearer token type.
/// Bearer = 1
///
/// Pop token type.
/// Pop = 2,
///
/// Ssh-cert token type.
/// SshCert = 3,
///
/// External token type.
/// External = 4,
///
/// Extension token type.
/// Extension = 5
/// </summary>
TokenType TelemetryTokenType { get; }
int TelemetryTokenType { get; }

/// <summary>
/// Prefix for the HTTP header that has the token. E.g. "Bearer" or "POP"
Expand All @@ -37,7 +53,7 @@ internal interface IAuthenticationScheme
/// <summary>
/// Creates the access token that goes into an Authorization HTTP header.
/// </summary>
string FormatAccessToken(MsalAccessTokenCacheItem msalAccessTokenCacheItem);
void FormatResult(AuthenticationResult authenticationResult);

/// <summary>
/// Expected to match the token_type parameter returned by ESTS. Used to disambiguate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

using System;
using System.Security.Cryptography;
using Microsoft.Identity.Client.AuthScheme.PoP;
using Microsoft.Identity.Client.Utils;

namespace Microsoft.Identity.Client.AuthScheme.PoP
{

/// <summary>
/// The default implementation will store a key in memory
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ namespace Microsoft.Identity.Client.AuthScheme.PoP
/// <summary>
/// This factory ensures key rotation every 8h
/// </summary>
internal static class PoPProviderFactory
internal static class PoPCryptoProviderFactory
{
private static InMemoryCryptoProvider s_currentProvider;
private static DateTime s_providerExpiration;

public /* public for test only */ static TimeSpan KeyRotationInterval { get; }
public /* public for test only */ static TimeSpan KeyRotationInterval { get; }
= TimeSpan.FromHours(8);

private static object s_lock = new object();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

namespace Microsoft.Identity.Client.AuthScheme.PoP
{
internal class PopAuthenticationScheme : IAuthenticationScheme
internal class PopAuthenticationOperation : IAuthenticationOperation
{
private readonly PoPAuthenticationConfiguration _popAuthenticationConfiguration;
private readonly IPoPCryptoProvider _popCryptoProvider;
Expand All @@ -33,7 +33,7 @@ internal class PopAuthenticationScheme : IAuthenticationScheme
/// Currently the signing credential algorithm is hard-coded to RSA with SHA256. Extensibility should be done
/// by integrating Wilson's SigningCredentials
/// </remarks>
public PopAuthenticationScheme(PoPAuthenticationConfiguration popAuthenticationConfiguration, IServiceBundle serviceBundle)
public PopAuthenticationOperation(PoPAuthenticationConfiguration popAuthenticationConfiguration, IServiceBundle serviceBundle)
{
if (serviceBundle == null)
{
Expand All @@ -48,7 +48,7 @@ public PopAuthenticationScheme(PoPAuthenticationConfiguration popAuthenticationC
KeyId = Base64UrlHelpers.Encode(keyThumbprint);
}

public TokenType TelemetryTokenType => TokenType.Pop;
public int TelemetryTokenType => (int)TokenType.Pop;

public string AuthorizationHeaderPrefix => Constants.PoPAuthHeaderPrefix;

Expand All @@ -67,25 +67,26 @@ public IReadOnlyDictionary<string, string> GetTokenRequestParams()
};
}

public string FormatAccessToken(MsalAccessTokenCacheItem msalAccessTokenCacheItem)
public void FormatResult(AuthenticationResult authenticationResult)
trwalke marked this conversation as resolved.
Show resolved Hide resolved
{
if (!_popAuthenticationConfiguration.SignHttpRequest)
{
return msalAccessTokenCacheItem.Secret;
// token will be signed by the caller
return;
}

var header = new JObject();
header[JsonWebTokenConstants.Algorithm] = _popCryptoProvider.CryptographicAlgorithm;
header[JsonWebTokenConstants.KeyId] = KeyId;
header[JsonWebTokenConstants.Type] = Constants.PoPTokenType;

var body = CreateBody(msalAccessTokenCacheItem);
var body = CreateBody(authenticationResult.AccessToken);

string popToken = CreateJWS(JsonHelper.JsonObjectToString(body), JsonHelper.JsonObjectToString(header));
return popToken;
authenticationResult.AccessToken = popToken;
}

private JObject CreateBody(MsalAccessTokenCacheItem msalAccessTokenCacheItem)
private JObject CreateBody(string accessToken)
{
var publicKeyJwk = JToken.Parse(_popCryptoProvider.CannonicalPublicKeyJwk);
var body = new JObject
Expand All @@ -96,7 +97,7 @@ private JObject CreateBody(MsalAccessTokenCacheItem msalAccessTokenCacheItem)
[PoPClaimTypes.JWK] = publicKeyJwk
},
[PoPClaimTypes.Ts] = DateTimeHelpers.CurrDateTimeInUnixTimestamp(),
[PoPClaimTypes.At] = msalAccessTokenCacheItem.Secret,
[PoPClaimTypes.At] = accessToken,
[PoPClaimTypes.Nonce] = _popAuthenticationConfiguration.Nonce ?? CreateSimpleNonce(),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@ namespace Microsoft.Identity.Client.AuthScheme.PoP
//Authentication Scheme used when MSAL Broker and pop are used together.
//Tokens acquired from brokers will not be saved in the local ache and MSAL will not search the local cache during silent authentication.
//This is because tokens are cached in the broker instead so MSAL will rely on the broker's cache for silent requests.
internal class PopBrokerAuthenticationScheme : IAuthenticationScheme
internal class PopBrokerAuthenticationOperation : IAuthenticationOperation
{
public TokenType TelemetryTokenType => TokenType.Pop;
public int TelemetryTokenType => (int)TokenType.Pop;

public string AuthorizationHeaderPrefix => Constants.PoPAuthHeaderPrefix;

public string KeyId => string.Empty;
trwalke marked this conversation as resolved.
Show resolved Hide resolved

public string AccessTokenType => Constants.PoPTokenType;

public string FormatAccessToken(MsalAccessTokenCacheItem msalAccessTokenCacheItem)
public void FormatResult(AuthenticationResult authenticationResult)
trwalke marked this conversation as resolved.
Show resolved Hide resolved
{
//no op
return msalAccessTokenCacheItem.Secret;
//no-op
}

public IReadOnlyDictionary<string, string> GetTokenRequestParams()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@

namespace Microsoft.Identity.Client.AuthScheme.SSHCertificates
{
internal class SSHCertAuthenticationScheme : IAuthenticationScheme
internal class SSHCertAuthenticationOperation : IAuthenticationOperation
{
internal const string SSHCertTokenType = "ssh-cert";
private readonly string _jwk;

public SSHCertAuthenticationScheme(string keyId, string jwk)
public SSHCertAuthenticationOperation(string keyId, string jwk)
{
if (string.IsNullOrEmpty(keyId))
{
Expand All @@ -29,7 +29,7 @@ public SSHCertAuthenticationScheme(string keyId, string jwk)
_jwk = jwk;
}

public TokenType TelemetryTokenType => TokenType.SshCert;
public int TelemetryTokenType => (int)TokenType.SshCert;

public string AuthorizationHeaderPrefix =>
throw new MsalClientException(
Expand All @@ -39,9 +39,9 @@ public SSHCertAuthenticationScheme(string keyId, string jwk)

public string KeyId { get; }

public string FormatAccessToken(MsalAccessTokenCacheItem msalAccessTokenCacheItem)
public void FormatResult(AuthenticationResult authenticationResult)
trwalke marked this conversation as resolved.
Show resolved Hide resolved
{
return msalAccessTokenCacheItem.Secret;
// no-op
}

public IReadOnlyDictionary<string, string> GetTokenRequestParams()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ internal enum TokenType
/// <summary>
/// External token type.
/// </summary>
External = 4
External = 4,

/// <summary>
/// Extension token type.
/// Extension = 5
/// </summary>
Extension = 5
}
}
Loading