Skip to content

Commit

Permalink
Add sendx5c parameter to Certificate factory class (#6699)
Browse files Browse the repository at this point in the history
* Add sendX5c parameter in certificate auth factory

* Add unit tests

* Remove commented property.

* Revert changes in CertificateServiceClientCredentialsFactory
  • Loading branch information
ceciliaavila authored Oct 12, 2023
1 parent 8cc12b8 commit 617394d
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,33 @@ public MsalAppCredentials(string appId, X509Certificate2 certificate, string aut
.Build();
}

/// <summary>
/// Initializes a new instance of the <see cref="MsalAppCredentials"/> class.
/// </summary>
/// <param name="appId">The Microsoft application id.</param>
/// <param name="certificate">The certificate to use for authentication.</param>
/// <param name="sendX5c">If true will send the public certificate to Azure AD along with the token request, so that
/// Azure AD can use it to validate the subject name based on a trusted issuer policy.</param>
/// <param name="validateAuthority">Optional switch for whether to validate the authority.</param>
/// <param name="authority">Optional authority.</param>
/// <param name="scope">Optional custom scope.</param>
/// <param name="logger">Optional <see cref="ILogger"/>.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2234:Pass system uri objects instead of strings", Justification = "Using string overload for legacy compatibility.")]
public MsalAppCredentials(string appId, X509Certificate2 certificate, bool sendX5c, string authority = null, string scope = null, bool validateAuthority = true, ILogger logger = null)
: this(
clientApplication: null,
appId: appId,
authority: authority,
scope: scope,
validateAuthority: validateAuthority,
logger: logger)
{
_clientApplication = ConfidentialClientApplicationBuilder.Create(appId)
.WithAuthority(authority ?? OAuthEndpoint, validateAuthority)
.WithCertificate(certificate, sendX5c)
.Build();
}

async Task<AuthenticatorResult> IAuthenticator.GetTokenAsync(bool forceRefresh)
{
var watch = Stopwatch.StartNew();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Identity.Client;
using Moq;
using Xunit;

namespace Microsoft.Bot.Connector.Tests.Authentication
{
public class MsalServiceClientCredentialsFactoryTests
{
private const string TestAppId = nameof(TestAppId);
private const string TestTenantId = nameof(TestTenantId);
private const string TestAudience = nameof(TestAudience);
private const string LoginEndpoint = "https://login.microsoftonline.com";
private const string LoginEndpointGov = "https://login.microsoftonline.us/MicrosoftServices.onmicrosoft.us";
private readonly Mock<ILogger> logger = new Mock<ILogger>();
private readonly Mock<IConfiguration> configuration = new Mock<IConfiguration>();
private readonly Mock<IConfidentialClientApplication> clientApplication = new Mock<IConfidentialClientApplication>();

[Fact]
public void ConstructorTests()
{
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);

Assert.NotNull(factory);
}

[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public async Task ShouldReturnEmptyCredentialsWithoutAppId(string appId)
{
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
var credentials = await factory.CreateCredentialsAsync(appId, TestAudience, LoginEndpoint, true, CancellationToken.None);

Assert.Equal(MsalAppCredentials.Empty, credentials);
}

[Fact]
public void ShouldThrowIfAppIdDoesNotMatch()
{
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(TestAppId);
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);

Assert.ThrowsAsync<InvalidOperationException>(() => factory.CreateCredentialsAsync(
"InvalidAppId", TestAudience, LoginEndpoint, true, CancellationToken.None));
}

[Fact]
public void ShouldCreateCredentials()
{
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(TestAppId);
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
var credentials = factory.CreateCredentialsAsync(TestAppId, TestAudience, LoginEndpoint, true, CancellationToken.None).GetAwaiter().GetResult();

Assert.NotNull(credentials);
Assert.IsType<MsalAppCredentials>(credentials);
}

[Fact]
public void ShouldCreateCredentialsForGoverment()
{
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(TestAppId);
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
var credentials = factory.CreateCredentialsAsync(TestAppId, TestAudience, LoginEndpointGov, true, CancellationToken.None).GetAwaiter().GetResult();

Assert.NotNull(credentials);
Assert.IsType<MsalAppCredentials>(credentials);
}

[Fact]
public void IsValidAppIdTest()
{
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(TestAppId);
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);

Assert.True(factory.IsValidAppIdAsync(TestAppId, CancellationToken.None).GetAwaiter().GetResult());
Assert.False(factory.IsValidAppIdAsync("InvalidAppId", CancellationToken.None).GetAwaiter().GetResult());
}

[Fact]
public void IsAuthenticationDisabledTest()
{
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(string.Empty);
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);

Assert.True(factory.IsAuthenticationDisabledAsync(CancellationToken.None).GetAwaiter().GetResult());
}
}
}

0 comments on commit 617394d

Please sign in to comment.