Skip to content

Commit 617394d

Browse files
authored
Add sendx5c parameter to Certificate factory class (#6699)
* Add sendX5c parameter in certificate auth factory * Add unit tests * Remove commented property. * Revert changes in CertificateServiceClientCredentialsFactory
1 parent 8cc12b8 commit 617394d

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

libraries/Microsoft.Bot.Connector/Authentication/MsalAppCredentials.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,33 @@ public MsalAppCredentials(string appId, X509Certificate2 certificate, string aut
106106
.Build();
107107
}
108108

109+
/// <summary>
110+
/// Initializes a new instance of the <see cref="MsalAppCredentials"/> class.
111+
/// </summary>
112+
/// <param name="appId">The Microsoft application id.</param>
113+
/// <param name="certificate">The certificate to use for authentication.</param>
114+
/// <param name="sendX5c">If true will send the public certificate to Azure AD along with the token request, so that
115+
/// Azure AD can use it to validate the subject name based on a trusted issuer policy.</param>
116+
/// <param name="validateAuthority">Optional switch for whether to validate the authority.</param>
117+
/// <param name="authority">Optional authority.</param>
118+
/// <param name="scope">Optional custom scope.</param>
119+
/// <param name="logger">Optional <see cref="ILogger"/>.</param>
120+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2234:Pass system uri objects instead of strings", Justification = "Using string overload for legacy compatibility.")]
121+
public MsalAppCredentials(string appId, X509Certificate2 certificate, bool sendX5c, string authority = null, string scope = null, bool validateAuthority = true, ILogger logger = null)
122+
: this(
123+
clientApplication: null,
124+
appId: appId,
125+
authority: authority,
126+
scope: scope,
127+
validateAuthority: validateAuthority,
128+
logger: logger)
129+
{
130+
_clientApplication = ConfidentialClientApplicationBuilder.Create(appId)
131+
.WithAuthority(authority ?? OAuthEndpoint, validateAuthority)
132+
.WithCertificate(certificate, sendX5c)
133+
.Build();
134+
}
135+
109136
async Task<AuthenticatorResult> IAuthenticator.GetTokenAsync(bool forceRefresh)
110137
{
111138
var watch = Stopwatch.StartNew();
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Microsoft.Bot.Connector.Authentication;
8+
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.Logging;
10+
using Microsoft.Identity.Client;
11+
using Moq;
12+
using Xunit;
13+
14+
namespace Microsoft.Bot.Connector.Tests.Authentication
15+
{
16+
public class MsalServiceClientCredentialsFactoryTests
17+
{
18+
private const string TestAppId = nameof(TestAppId);
19+
private const string TestTenantId = nameof(TestTenantId);
20+
private const string TestAudience = nameof(TestAudience);
21+
private const string LoginEndpoint = "https://login.microsoftonline.com";
22+
private const string LoginEndpointGov = "https://login.microsoftonline.us/MicrosoftServices.onmicrosoft.us";
23+
private readonly Mock<ILogger> logger = new Mock<ILogger>();
24+
private readonly Mock<IConfiguration> configuration = new Mock<IConfiguration>();
25+
private readonly Mock<IConfidentialClientApplication> clientApplication = new Mock<IConfidentialClientApplication>();
26+
27+
[Fact]
28+
public void ConstructorTests()
29+
{
30+
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
31+
32+
Assert.NotNull(factory);
33+
}
34+
35+
[Theory]
36+
[InlineData(null)]
37+
[InlineData("")]
38+
[InlineData(" ")]
39+
public async Task ShouldReturnEmptyCredentialsWithoutAppId(string appId)
40+
{
41+
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
42+
var credentials = await factory.CreateCredentialsAsync(appId, TestAudience, LoginEndpoint, true, CancellationToken.None);
43+
44+
Assert.Equal(MsalAppCredentials.Empty, credentials);
45+
}
46+
47+
[Fact]
48+
public void ShouldThrowIfAppIdDoesNotMatch()
49+
{
50+
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(TestAppId);
51+
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
52+
53+
Assert.ThrowsAsync<InvalidOperationException>(() => factory.CreateCredentialsAsync(
54+
"InvalidAppId", TestAudience, LoginEndpoint, true, CancellationToken.None));
55+
}
56+
57+
[Fact]
58+
public void ShouldCreateCredentials()
59+
{
60+
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(TestAppId);
61+
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
62+
var credentials = factory.CreateCredentialsAsync(TestAppId, TestAudience, LoginEndpoint, true, CancellationToken.None).GetAwaiter().GetResult();
63+
64+
Assert.NotNull(credentials);
65+
Assert.IsType<MsalAppCredentials>(credentials);
66+
}
67+
68+
[Fact]
69+
public void ShouldCreateCredentialsForGoverment()
70+
{
71+
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(TestAppId);
72+
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
73+
var credentials = factory.CreateCredentialsAsync(TestAppId, TestAudience, LoginEndpointGov, true, CancellationToken.None).GetAwaiter().GetResult();
74+
75+
Assert.NotNull(credentials);
76+
Assert.IsType<MsalAppCredentials>(credentials);
77+
}
78+
79+
[Fact]
80+
public void IsValidAppIdTest()
81+
{
82+
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(TestAppId);
83+
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
84+
85+
Assert.True(factory.IsValidAppIdAsync(TestAppId, CancellationToken.None).GetAwaiter().GetResult());
86+
Assert.False(factory.IsValidAppIdAsync("InvalidAppId", CancellationToken.None).GetAwaiter().GetResult());
87+
}
88+
89+
[Fact]
90+
public void IsAuthenticationDisabledTest()
91+
{
92+
configuration.Setup(x => x.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey).Value).Returns(string.Empty);
93+
var factory = new MsalServiceClientCredentialsFactory(configuration.Object, clientApplication.Object, logger.Object);
94+
95+
Assert.True(factory.IsAuthenticationDisabledAsync(CancellationToken.None).GetAwaiter().GetResult());
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)