public async Task POP_ShrValidation_Async() { using (var httpManager = new MockHttpManager()) { ConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(TestConstants.ClientId) .WithClientSecret(TestConstants.ClientSecret) .WithHttpManager(httpManager) .WithExperimentalFeatures(true) .BuildConcrete(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(ProtectedUrl)); var popConfig = new PoPAuthenticationConfiguration(request); var provider = PoPProviderFactory.GetOrCreateProvider(); httpManager.AddInstanceDiscoveryMockHandler(); httpManager.AddMockHandlerSuccessfulClientCredentialTokenResponseMessage(tokenType: "pop"); // Act var result = await app.AcquireTokenForClient(TestConstants.s_scope.ToArray()) .WithAuthority(TestConstants.AuthorityUtidTenant) .WithProofOfPossession(popConfig) .ExecuteAsync() .ConfigureAwait(false); // access token parsing can be done with MSAL's id token parsing logic var claims = IdToken.Parse(result.AccessToken).ClaimsPrincipal; Assert.IsTrue(!string.IsNullOrEmpty(claims.FindAll("nonce").Single().Value)); AssertSingedHttpRequestClaims(provider, claims); } }
public async Task POP_WithMissingNonceForPCA_Async() { using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithBrokerPreview() .WithExperimentalFeatures() .WithHttpManager(httpManager) .BuildConcrete(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(ProtectedUrl)); var popConfig = new PoPAuthenticationConfiguration(request); var provider = PoPProviderFactory.GetOrCreateProvider(); await AssertException.TaskThrowsAsync <ArgumentNullException>(() => app.AcquireTokenInteractive(TestConstants.s_scope.ToArray()) .WithAuthority(TestConstants.AuthorityUtidTenant) .WithProofOfPossession(null, HttpMethod.Get, new Uri(app.Authority)) .ExecuteAsync()) .ConfigureAwait(false); await AssertException.TaskThrowsAsync <ArgumentNullException>(() => app.AcquireTokenSilent(TestConstants.s_scope.ToArray(), "loginHint") .WithAuthority(TestConstants.AuthorityUtidTenant) .WithProofOfPossession(null, HttpMethod.Get, new Uri(app.Authority)) .ExecuteAsync()) .ConfigureAwait(false); } }
public async Task POP_NoHttpRequest_Async() { using (var httpManager = new MockHttpManager()) { ConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(TestConstants.ClientId) .WithClientSecret(TestConstants.ClientSecret) .WithHttpManager(httpManager) .WithExperimentalFeatures(true) .BuildConcrete(); // no HTTP method binding, but custom nonce var popConfig = new PoPAuthenticationConfiguration() { Nonce = CustomNonce }; var provider = PoPProviderFactory.GetOrCreateProvider(); httpManager.AddInstanceDiscoveryMockHandler(); httpManager.AddMockHandlerSuccessfulClientCredentialTokenResponseMessage(tokenType: "pop"); // Act var result = await app.AcquireTokenForClient(TestConstants.s_scope.ToArray()) .WithAuthority(TestConstants.AuthorityUtidTenant) .WithProofOfPossession(popConfig) .ExecuteAsync() .ConfigureAwait(false); // access token parsing can be done with MSAL's id token parsing logic var claims = IdToken.Parse(result.AccessToken).ClaimsPrincipal; Assert.AreEqual(CustomNonce, claims.FindAll("nonce").Single().Value); AssertTsAndJwkClaims(provider, claims); Assert.IsFalse(claims.FindAll("m").Any()); Assert.IsFalse(claims.FindAll("u").Any()); Assert.IsFalse(claims.FindAll("p").Any()); } }
public override IPoPCryptoProvider GetDefaultPoPCryptoProvider() { return(PoPProviderFactory.GetOrCreateProvider()); }
public async Task ValidateKeyExpirationAsync() { using (var harness = CreateTestHarness()) { harness.HttpManager.AddInstanceDiscoveryMockHandler(); PoPAuthenticationConfiguration popConfig = new PoPAuthenticationConfiguration(new Uri("https://www.contoso.com/path1/path2?queryParam1=a&queryParam2=b")); popConfig.HttpMethod = HttpMethod.Get; popConfig.PopCryptoProvider = new InMemoryCryptoProvider(); var app = ConfidentialClientApplicationBuilder.Create(TestConstants.ClientId) .WithHttpManager(harness.HttpManager) .WithExperimentalFeatures() .WithClientSecret("some-secret") .BuildConcrete(); harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost( TestConstants.AuthorityCommonTenant, null, null, false, MockHelpers.CreateSuccessResponseMessage(MockHelpers.GetPopTokenResponse())); Guid correlationId = Guid.NewGuid(); TestClock testClock = new TestClock(); testClock.TestTime = DateTime.UtcNow; var provider = PoPProviderFactory.GetOrCreateProvider(testClock); await app.AcquireTokenForClient(TestConstants.s_scope) .WithProofOfPossession(popConfig) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); var JWK = provider.CannonicalPublicKeyJwk; //Advance time 7 hours. Should still be the same key testClock.TestTime = testClock.TestTime + TimeSpan.FromSeconds(60 * 60 * 7); harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost( TestConstants.AuthorityCommonTenant, null, null, false, MockHelpers.CreateSuccessResponseMessage(MockHelpers.GetPopTokenResponse())); provider = PoPProviderFactory.GetOrCreateProvider(testClock); await app.AcquireTokenForClient(TestConstants.s_scope) .WithProofOfPossession(popConfig) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.IsTrue(JWK == provider.CannonicalPublicKeyJwk); //Advance time 2 hours. Should be a different key testClock.TestTime = testClock.TestTime + TimeSpan.FromSeconds(60 * 60 * 2); harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost( TestConstants.AuthorityCommonTenant, null, null, false, MockHelpers.CreateSuccessResponseMessage(MockHelpers.GetPopTokenResponse())); provider = PoPProviderFactory.GetOrCreateProvider(testClock); await app.AcquireTokenForClient(TestConstants.s_scope) .WithProofOfPossession(popConfig) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.IsTrue(JWK != provider.CannonicalPublicKeyJwk); } }
public async Task ValidateKeyExpirationAsync() { using (var harness = CreateTestHarness()) { harness.HttpManager.AddInstanceDiscoveryMockHandler(); HttpRequestMessage request1 = new HttpRequestMessage(HttpMethod.Get, new Uri("https://www.contoso.com/path1/path2?queryParam1=a&queryParam2=b")); var app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithHttpManager(harness.HttpManager) .WithExperimentalFeatures() .BuildConcrete(); MsalMockHelpers.ConfigureMockWebUI( app.ServiceBundle.PlatformProxy, AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code")); harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost( TestConstants.AuthorityCommonTenant, null, null, false, MockHelpers.CreateSuccessResponseMessage(MockHelpers.GetPopTokenResponse())); Guid correlationId = Guid.NewGuid(); TestClock testClock = new TestClock(); testClock.TestTime = DateTime.UtcNow; var provider = PoPProviderFactory.GetOrCreateProvider(testClock); await app.AcquireTokenInteractive(TestConstants.s_scope) .WithProofOfPosession(request1, provider) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); var JWK = provider.CannonicalPublicKeyJwk; //Advance time 7 hours. Should still be the same key testClock.TestTime = testClock.TestTime + TimeSpan.FromSeconds(60 * 60 * 7); harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost( TestConstants.AuthorityCommonTenant, null, null, false, MockHelpers.CreateSuccessResponseMessage(MockHelpers.GetPopTokenResponse())); provider = PoPProviderFactory.GetOrCreateProvider(testClock); await app.AcquireTokenInteractive(TestConstants.s_scope) .WithProofOfPosession(request1, provider) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.IsTrue(JWK == provider.CannonicalPublicKeyJwk); //Advance time 2 hours. Should be a different key testClock.TestTime = testClock.TestTime + TimeSpan.FromSeconds(60 * 60 * 2); harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost( TestConstants.AuthorityCommonTenant, null, null, false, MockHelpers.CreateSuccessResponseMessage(MockHelpers.GetPopTokenResponse())); provider = PoPProviderFactory.GetOrCreateProvider(testClock); await app.AcquireTokenInteractive(TestConstants.s_scope) .WithProofOfPosession(request1, provider) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.IsTrue(JWK != provider.CannonicalPublicKeyJwk); } }
public async Task CacheKey_Includes_POPKid_Async() { using (var httpManager = new MockHttpManager()) { ConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(TestConstants.ClientId) .WithClientSecret(TestConstants.ClientSecret) .WithHttpManager(httpManager) .WithExperimentalFeatures(true) .BuildConcrete(); var testTimeService = new TestTimeService(); PoPProviderFactory.TimeService = testTimeService; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(ProtectedUrl)); var popConfig = new PoPAuthenticationConfiguration(request); var cacheAccess = app.AppTokenCache.RecordAccess(); httpManager.AddInstanceDiscoveryMockHandler(); httpManager.AddMockHandlerSuccessfulClientCredentialTokenResponseMessage(tokenType: "pop"); // Act Trace.WriteLine("1. AcquireTokenForClient "); var result = await app.AcquireTokenForClient(TestConstants.s_scope.ToArray()) .WithAuthority(TestConstants.AuthorityUtidTenant) .WithProofOfPossession(popConfig) .ExecuteAsync() .ConfigureAwait(false); // Assert Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); string expectedKid = GetKidFromJwk(PoPProviderFactory.GetOrCreateProvider().CannonicalPublicKeyJwk); string actualCacheKey = cacheAccess.LastBeforeAccessNotificationArgs.SuggestedCacheKey; Assert.AreEqual( string.Format( CultureInfo.InvariantCulture, "{0}{1}_{2}_AppTokenCache", expectedKid, TestConstants.ClientId, TestConstants.Utid), actualCacheKey); // Arrange - force a new key by moving to the future (PoPProviderFactory.TimeService as TestTimeService).MoveToFuture( PoPProviderFactory.KeyRotationInterval.Add(TimeSpan.FromMinutes(10))); httpManager.AddMockHandlerSuccessfulClientCredentialTokenResponseMessage(tokenType: "pop"); // Act Trace.WriteLine("1. AcquireTokenForClient again, after time passes - expect POP key rotation"); result = await app.AcquireTokenForClient(TestConstants.s_scope.ToArray()) .WithAuthority(TestConstants.AuthorityUtidTenant) .WithProofOfPossession(popConfig) .ExecuteAsync() .ConfigureAwait(false); // Assert Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); string expectedKid2 = GetKidFromJwk(PoPProviderFactory.GetOrCreateProvider().CannonicalPublicKeyJwk); string actualCacheKey2 = cacheAccess.LastBeforeAccessNotificationArgs.SuggestedCacheKey; Assert.AreEqual( string.Format( CultureInfo.InvariantCulture, "{0}{1}_{2}_AppTokenCache", expectedKid2, TestConstants.ClientId, TestConstants.Utid), actualCacheKey2); Assert.AreNotEqual(actualCacheKey, actualCacheKey2); } }