Skip to content

Commit

Permalink
Fix for 4913 - sendX5C for ROPC CCA (#4917)
Browse files Browse the repository at this point in the history
* Fix for 4913 - sendX5C for ROPC CCA

* fix
  • Loading branch information
bgavrilMS authored Sep 9, 2024
1 parent f772a74 commit a805fca
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace Microsoft.Identity.Client
{
/// <summary>
/// Parameter builder for the <see cref="IConfidentialClientApplication.AcquireTokenByUsernamePassword(IEnumerable{string}, string, string)"/>
/// Parameter builder for the <see cref="IByUsernameAndPassword.AcquireTokenByUsernamePassword(IEnumerable{string}, string, string)"/>
/// operation. See https://aka.ms/msal-net-up
/// </summary>
public sealed class AcquireTokenByUsernameAndPasswordConfidentialParameterBuilder :
Expand Down Expand Up @@ -67,5 +67,16 @@ internal override ApiEvent.ApiIds CalculateApiEventId()
{
return ApiEvent.ApiIds.AcquireTokenByUsernamePassword;
}

/// <inheritdoc/>
protected override void Validate()
{
base.Validate();

if (Parameters.SendX5C == null)
{
Parameters.SendX5C = ServiceBundle.Config?.SendX5C ?? false;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ public async Task<AuthenticationResult> ExecuteAsync(
commonParameters,
requestContext,
_confidentialClientApplication.UserTokenCacheInternal).ConfigureAwait(false);

requestParams.SendX5C = usernamePasswordParameters.SendX5C ?? false;

var handler = new UsernamePasswordRequest(
ServiceBundle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,5 @@ internal abstract class AbstractAcquireTokenConfidentialClientParameters
/// This overrides application config settings.
/// </summary>
public bool? SendX5C { get; set; }

/// <summary>
/// if <c>true</c> then Spa code param will be sent via AcquireTokenByAuthorizeCode
/// </summary>
public bool SpaCode { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ internal class AcquireTokenByAuthorizationCodeParameters : AbstractAcquireTokenC

public string PkceCodeVerifier { get; set; }

/// <summary>
/// if <c>true</c> then Spa code param will be sent via AcquireTokenByAuthorizeCode
/// </summary>
public bool SpaCode { get; set; }

public void LogParameters(ILoggerAdapter logger)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
// Licensed under the MIT License.

using System.Security;
using System.Text;
using Microsoft.Identity.Client.Core;

namespace Microsoft.Identity.Client.ApiConfig.Parameters
{

internal class AcquireTokenByUsernamePasswordParameters : AbstractAcquireTokenByUsernameParameters, IAcquireTokenParameters
{
public string Password { get; set; }

public bool? SendX5C { get; set; } // CCA only

/// <inheritdoc/>
public void LogParameters(ILoggerAdapter logger)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,22 @@ private async Task RunHappyPathTestAsync(LabResponse labResponse, string federat
else
{
IConfidentialAppSettings settings = ConfidentialAppSettings.GetSettings(cloud);
clientApp = ConfidentialClientApplicationBuilder
var clientAppBuilder = ConfidentialClientApplicationBuilder
.Create(settings.ClientId)
.WithTestLogging()
.WithHttpClientFactory(factory)
.WithAuthority(labResponse.Lab.Authority, "organizations")
.WithClientSecret(settings.GetSecret())
.Build();
.WithAuthority(labResponse.Lab.Authority, "organizations");

if (cloud == Cloud.Arlington)
{
clientAppBuilder.WithClientSecret(settings.GetSecret());
}
else
{
clientAppBuilder.WithCertificate(settings.GetCertificate(), true);
}

clientApp = clientAppBuilder.Build();
}

AuthenticationResult authResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,41 @@ await app.AcquireTokenByAuthorizationCode(TestConstants.s_scope, TestConstants.D
}
}


// regression test for https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/4913
[DataTestMethod]
[DataRow(true)]
[DataRow(false)]
public async Task RopcCcaSendsX5CAsync(bool sendX5C)
{
using (var harness = CreateTestHarness())
{
var certificate = CertHelper.GetOrCreateTestCert();
var exportedCertificate = Convert.ToBase64String(certificate.Export(X509ContentType.Cert));

var app = ConfidentialClientApplicationBuilder
.Create(TestConstants.ClientId)
.WithHttpManager(harness.HttpManager)
.WithCertificate(certificate, sendX5C)
.Build();

harness.HttpManager.AddInstanceDiscoveryMockHandler();

harness.HttpManager.AddMockHandler(
CreateTokenResponseHttpHandlerWithX5CValidation(
clientCredentialFlow: false,
expectedX5C: sendX5C ? exportedCertificate: null));

var result = await (app as IByUsernameAndPassword)
.AcquireTokenByUsernamePassword(
TestConstants.s_scope,
TestConstants.Username,
TestConstants.DefaultPassword)
.ExecuteAsync()
.ConfigureAwait(false);
}
}

private static string ComputeCertThumbprint(X509Certificate2 certificate, bool useSha2)
{
string thumbprint = null;
Expand Down

0 comments on commit a805fca

Please sign in to comment.