Skip to content

Commit 369d589

Browse files
Support for SNI MTLS POP with DSTS Authorities (#5059)
* dsts initial * remove const --------- Co-authored-by: Gladwin Johnson <[email protected]>
1 parent 77ca057 commit 369d589

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

src/client/Microsoft.Identity.Client/ApiConfig/AcquireTokenForClientParameterBuilder.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ protected override void Validate()
135135
{
136136
string authorityUri = ServiceBundle.Config.Authority.AuthorityInfo.CanonicalAuthority.AbsoluteUri;
137137

138-
if (ServiceBundle.Config.Authority.AuthorityInfo.AuthorityType != AuthorityType.Aad)
138+
if (ServiceBundle.Config.Authority.AuthorityInfo.AuthorityType != AuthorityType.Aad &&
139+
ServiceBundle.Config.Authority.AuthorityInfo.AuthorityType != AuthorityType.Dsts)
139140
{
140141
throw new MsalClientException(
141142
MsalError.InvalidAuthorityType,
@@ -149,7 +150,9 @@ protected override void Validate()
149150
MsalErrorMessage.MtlsNonTenantedAuthorityNotAllowedMessage);
150151
}
151152

152-
if (string.IsNullOrEmpty(ServiceBundle.Config.AzureRegion))
153+
// Check for Azure region only if the authority is AAD
154+
if (ServiceBundle.Config.Authority.AuthorityInfo.AuthorityType == AuthorityType.Aad &&
155+
string.IsNullOrEmpty(ServiceBundle.Config.AzureRegion))
153156
{
154157
throw new MsalClientException(
155158
MsalError.MtlsPopWithoutRegion,

tests/Microsoft.Identity.Test.Unit/PublicApiTests/MtlsPopTests.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,5 +668,73 @@ private static HttpResponseMessage CreateResponse(
668668
{
669669
return MockHelpers.CreateSuccessfulClientCredentialTokenResponseMessage(token, expiresIn, tokenType);
670670
}
671+
672+
[TestMethod]
673+
public async Task AcquireTokenForClient_WithMtlsPop_Dsts_SuccessAsync()
674+
{
675+
string authorityUrl = TestConstants.DstsAuthorityTenanted;
676+
677+
// Modify the endpoint based on the authorityUrl
678+
string expectedTokenEndpoint = $"{authorityUrl}oauth2/v2.0/token";
679+
680+
using (var httpManager = new MockHttpManager())
681+
{
682+
// Set up mock handler with expected token endpoint URL
683+
httpManager.AddMockHandler(new MockHttpMessageHandler()
684+
{
685+
ExpectedUrl = expectedTokenEndpoint,
686+
ExpectedMethod = HttpMethod.Post,
687+
ResponseMessage = MockHelpers.CreateSuccessfulClientCredentialTokenResponseMessage(tokenType: "mtls_pop")
688+
});
689+
690+
var app = ConfidentialClientApplicationBuilder.Create(TestConstants.ClientId)
691+
.WithCertificate(s_testCertificate)
692+
.WithAuthority(authorityUrl)
693+
.WithExperimentalFeatures()
694+
.WithHttpManager(httpManager)
695+
.BuildConcrete();
696+
697+
// First token acquisition - should hit the identity provider
698+
AuthenticationResult result = await app.AcquireTokenForClient(TestConstants.s_scope)
699+
.WithMtlsProofOfPossession()
700+
.ExecuteAsync()
701+
.ConfigureAwait(false);
702+
703+
Assert.AreEqual("header.payload.signature", result.AccessToken);
704+
Assert.AreEqual(Constants.MtlsPoPAuthHeaderPrefix, result.TokenType);
705+
Assert.AreEqual(null, result.AuthenticationResultMetadata.RegionDetails.RegionUsed);
706+
Assert.AreEqual(expectedTokenEndpoint, result.AuthenticationResultMetadata.TokenEndpoint);
707+
708+
// Second token acquisition - should retrieve from cache
709+
AuthenticationResult secondResult = await app.AcquireTokenForClient(TestConstants.s_scope)
710+
.WithMtlsProofOfPossession()
711+
.ExecuteAsync()
712+
.ConfigureAwait(false);
713+
714+
Assert.AreEqual("header.payload.signature", secondResult.AccessToken);
715+
Assert.AreEqual(Constants.MtlsPoPAuthHeaderPrefix, secondResult.TokenType);
716+
Assert.AreEqual(TokenSource.Cache, secondResult.AuthenticationResultMetadata.TokenSource);
717+
}
718+
}
719+
720+
[TestMethod]
721+
public async Task MtlsPopDstsCommonAuthorityFailsAsync()
722+
{
723+
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
724+
.Create(TestConstants.ClientId)
725+
.WithAuthority(TestConstants.DstsAuthorityCommon)
726+
.WithCertificate(s_testCertificate)
727+
.WithExperimentalFeatures()
728+
.Build();
729+
730+
// Set WithMtlsProofOfPossession on the request without specifying an authority
731+
MsalClientException ex = await AssertException.TaskThrowsAsync<MsalClientException>(() =>
732+
app.AcquireTokenForClient(TestConstants.s_scope)
733+
.WithMtlsProofOfPossession()
734+
.ExecuteAsync())
735+
.ConfigureAwait(false);
736+
737+
Assert.AreEqual(MsalError.MissingTenantedAuthority, ex.ErrorCode);
738+
}
671739
}
672740
}

0 commit comments

Comments
 (0)