private IConfidentialClientApplication BuildCCA( IConfidentialAppSettings settings, HttpSnifferClientFactory factory, bool useClaims = false, string region = ConfidentialClientApplication.AttemptRegionDiscovery) { var builder = ConfidentialClientApplicationBuilder.Create(settings.ClientId); if (useClaims) { builder.WithClientAssertion(GetSignedClientAssertionUsingMsalInternal(settings.ClientId, GetClaims(settings))); } else { builder.WithCertificate(settings.GetCertificate()); } builder.WithAuthority($@"https://{settings.Environment}/{settings.TenantId}") .WithTestLogging() .WithExperimentalFeatures(true) .WithHttpClientFactory(factory); if (region != null) { builder.WithAzureRegion(region); } return(builder.Build()); }
public async Task LegacyPoPAsync() { IConfidentialAppSettings settings = ConfidentialAppSettings.GetSettings(Cloud.Public); X509Certificate2 clientCredsCert = settings.GetCertificate(); RsaSecurityKey popKey = CreateRsaSecurityKey(); var cca = ConfidentialClientApplicationBuilder .Create(settings.ClientId) .WithAuthority(settings.Authority, true) .WithExperimentalFeatures(true) .WithTestLogging() .Build(); var result = await cca.AcquireTokenForClient(settings.AppScopes) .WithProofOfPosessionKeyId(popKey.KeyId) .OnBeforeTokenRequest((data) => { ModifyRequestWithLegacyPop(data, settings, clientCredsCert, popKey); return(Task.CompletedTask); }) .ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); MsalAccessTokenCacheItem at = (cca.AppTokenCache as ITokenCacheInternal).Accessor.GetAllAccessTokens().Single(); Assert.AreEqual(at.KeyId, popKey.KeyId); result = await cca.AcquireTokenForClient(settings.AppScopes) .WithProofOfPosessionKeyId(popKey.KeyId) .OnBeforeTokenRequest((data) => { ModifyRequestWithLegacyPop(data, settings, clientCredsCert, popKey); return(Task.CompletedTask); }).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource); at = (cca.AppTokenCache as ITokenCacheInternal).Accessor.GetAllAccessTokens().Single(); Assert.AreEqual(at.KeyId, popKey.KeyId); RsaSecurityKey popKey2 = CreateRsaSecurityKey(); result = await cca.AcquireTokenForClient(settings.AppScopes) .WithProofOfPosessionKeyId(popKey2.KeyId) .OnBeforeTokenRequest((data) => { ModifyRequestWithLegacyPop(data, settings, clientCredsCert, popKey2); return(Task.CompletedTask); }).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); var ats = (cca.AppTokenCache as ITokenCacheInternal).Accessor.GetAllAccessTokens(); Assert.IsNotNull(ats.SingleOrDefault(a => a.KeyId == popKey2.KeyId)); Assert.IsNotNull(ats.SingleOrDefault(a => a.KeyId == popKey.KeyId)); }
private async Task RunClientCredsAsync(Cloud cloud, CredentialType credentialType, bool UseAppIdUri = false, bool sendX5C = false) { Trace.WriteLine($"Running test with settings for cloud {cloud}, credential type {credentialType}"); IConfidentialAppSettings settings = ConfidentialAppSettings.GetSettings(cloud); settings.UseAppIdUri = UseAppIdUri; AuthenticationResult authResult; IConfidentialClientApplication confidentialApp = CreateApp(credentialType, settings, sendX5C); var appCacheRecorder = confidentialApp.AppTokenCache.RecordAccess(); Guid correlationId = Guid.NewGuid(); authResult = await confidentialApp .AcquireTokenForClient(settings.AppScopes) .WithCorrelationId(correlationId) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); MsalAssert.AssertAuthResult(authResult); appCacheRecorder.AssertAccessCounts(1, 1); Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource); Assert.IsTrue(appCacheRecorder.LastAfterAccessNotificationArgs.IsApplicationCache); Assert.IsTrue(appCacheRecorder.LastAfterAccessNotificationArgs.HasTokens); Assert.AreEqual(correlationId, appCacheRecorder.LastAfterAccessNotificationArgs.CorrelationId); Assert.AreEqual(correlationId, appCacheRecorder.LastBeforeAccessNotificationArgs.CorrelationId); Assert.IsTrue(authResult.AuthenticationResultMetadata.DurationTotalInMs > 0); Assert.IsTrue(authResult.AuthenticationResultMetadata.DurationInHttpInMs > 0); Assert.AreEqual( GetExpectedCacheKey(settings.ClientId, settings.TenantId), appCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey); // Call again to ensure token cache is hit authResult = await confidentialApp .AcquireTokenForClient(settings.AppScopes) .ExecuteAsync() .ConfigureAwait(false); MsalAssert.AssertAuthResult(authResult); Assert.IsTrue(authResult.AuthenticationResultMetadata.DurationInHttpInMs == 0); appCacheRecorder.AssertAccessCounts(2, 1); Assert.AreEqual(TokenSource.Cache, authResult.AuthenticationResultMetadata.TokenSource); Assert.IsTrue(appCacheRecorder.LastAfterAccessNotificationArgs.IsApplicationCache); Assert.IsTrue(appCacheRecorder.LastAfterAccessNotificationArgs.HasTokens); Assert.AreNotEqual(correlationId, appCacheRecorder.LastAfterAccessNotificationArgs.CorrelationId); Assert.AreNotEqual(correlationId, appCacheRecorder.LastBeforeAccessNotificationArgs.CorrelationId); Assert.AreEqual( GetExpectedCacheKey(settings.ClientId, settings.TenantId), appCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey); }
private static IDictionary <string, string> GetClaims(IConfidentialAppSettings settings) { DateTime validFrom = DateTime.UtcNow; var nbf = ConvertToTimeT(validFrom); var exp = ConvertToTimeT(validFrom + TimeSpan.FromSeconds(TestConstants.JwtToAadLifetimeInSeconds)); return(new Dictionary <string, string>() { { "aud", $"https://{settings.Environment}/{settings.TenantId}/v2.0" }, { "exp", exp.ToString(CultureInfo.InvariantCulture) }, { "iss", settings.ClientId }, { "jti", Guid.NewGuid().ToString() }, { "nbf", nbf.ToString(CultureInfo.InvariantCulture) }, { "sub", settings.ClientId }, { "ip", "192.168.2.1" } }); }
public async Task WithOnBeforeTokenRequest_TestAsync(Cloud cloud, RunOn runOn) { IConfidentialAppSettings settings = ConfidentialAppSettings.GetSettings(cloud); AuthenticationResult authResult; IConfidentialClientApplication confidentialApp = ConfidentialClientApplicationBuilder .Create(settings.ClientId) .WithAuthority(settings.Authority, true) .WithExperimentalFeatures(true) .WithTestLogging() .Build(); authResult = await confidentialApp .AcquireTokenForClient(settings.AppScopes) .OnBeforeTokenRequest((data) => { ModifyRequest(data, settings.GetCertificate()); // Adding a certificate via handler instead of using WithCertificate return(Task.CompletedTask); }) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource); // Call again to ensure token cache is hit authResult = await confidentialApp .AcquireTokenForClient(settings.AppScopes) .OnBeforeTokenRequest((data) => { throw new InvalidOperationException("Should not be invoking this callback when the token is fetched from the cache"); }) .ExecuteAsync() .ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, authResult.AuthenticationResultMetadata.TokenSource); }
private static IConfidentialClientApplication CreateApp(CredentialType credentialType, IConfidentialAppSettings settings) { var builder = ConfidentialClientApplicationBuilder .Create(settings.ClientId) .WithAuthority(settings.Authority, true) .WithTestLogging(); switch (credentialType) { case CredentialType.Cert: builder.WithCertificate(settings.GetCertificate()); break; case CredentialType.Secret: builder.WithClientSecret(settings.GetSecret()); break; case CredentialType.ClientAssertion_Manual: var aud = settings.Cloud == Cloud.Adfs ? settings.Authority + "/oauth2/token" : settings.Authority + "/oauth2/v2.0/token"; string signedAssertionManual = GetSignedClientAssertionManual( settings.ClientId, aud, // for AAD use v2.0, but not for ADFS settings.GetCertificate()); builder.WithClientAssertion(signedAssertionManual); break; case CredentialType.ClientAssertion_Wilson: var aud2 = settings.Cloud == Cloud.Adfs ? settings.Authority + "/oauth2/token" : settings.Authority + "/oauth2/v2.0/token"; string clientAssertion = GetSignedClientAssertionUsingWilson( settings.ClientId, aud2, settings.GetCertificate()); builder.WithClientAssertion(clientAssertion); break; case CredentialType.ClientClaims_ExtraClaims: builder.WithClientClaims(settings.GetCertificate(), GetClaims(true), mergeWithDefaultClaims: false); break; case CredentialType.ClientClaims_MergeClaims: builder.WithClientClaims(settings.GetCertificate(), GetClaims(false), mergeWithDefaultClaims: true); break; default: throw new NotImplementedException(); } var confidentialApp = builder.Build(); return(confidentialApp); }
static async Task Main(string[] args) { s_appSettings = ConfidentialAppSettings.GetSettings(Cloud.Public); while (true) { Console.Clear(); Console.WriteLine(@" 1: Regional with a valid user-specified region 2: Regional with environment variable 3: Regional with IMDS call (without environment variable, test in Azure VM) 4: Acquire token with global, then regional 5: Acquire token with regional, then global 6: Acquire token twice in a row with regional (tests for double region appending regression) 7: Acquire token twice in a row with global 8: Regional with an invalid user-specified region 0. Exit app Enter your selection: "); int.TryParse(Console.ReadLine(), out var menuSelection); try { switch (menuSelection) { case 1: // Regional with a valid user-specified region await AcquireTokenAsync(region : "westus").ConfigureAwait(false); break; case 2: // Regional auto-detect with environment variable await AcquireTokenAsync(region : ConfidentialClientApplication.AttemptRegionDiscovery).ConfigureAwait(false); break; case 3: // Regional auto-detect with IMDS call (without environment variable, test in Azure VM) await AcquireTokenAsync(region : ConfidentialClientApplication.AttemptRegionDiscovery, setEnvVariable : false).ConfigureAwait(false); break; case 4: // Acquire token with global, then regional await AcquireTokenAsync(region : string.Empty).ConfigureAwait(false); await AcquireTokenAsync(region : ConfidentialClientApplication.AttemptRegionDiscovery).ConfigureAwait(false); break; case 5: // Acquire token with regional, then global await AcquireTokenAsync(region : ConfidentialClientApplication.AttemptRegionDiscovery).ConfigureAwait(false); await AcquireTokenAsync(region : string.Empty).ConfigureAwait(false); break; case 6: // Acquire token twice in a row with regional (tests for double region appending regression) await AcquireTokenAsync(region : ConfidentialClientApplication.AttemptRegionDiscovery).ConfigureAwait(false); await AcquireTokenAsync(region : ConfidentialClientApplication.AttemptRegionDiscovery).ConfigureAwait(false); break; case 7: // Acquire token twice in a row with global await AcquireTokenAsync(region : string.Empty).ConfigureAwait(false); await AcquireTokenAsync(region : string.Empty).ConfigureAwait(false); break; case 8: // Regional with an invalid user-specified region await AcquireTokenAsync(region : "invalidRegion").ConfigureAwait(false); break; case 0: return; default: break; } } catch (Exception ex) { Log(LogLevel.Error, ex.Message, false); Log(LogLevel.Error, ex.StackTrace, false); } Console.WriteLine("\n\nHit 'ENTER' to exit..."); Console.ReadLine(); } }
private static void ModifyRequestWithLegacyPop(OnBeforeTokenRequestData data, IConfidentialAppSettings settings, X509Certificate2 clientCredsCert, RsaSecurityKey popKey) { var clientCredsSigningCredentials = new SigningCredentials(new X509SecurityKey(clientCredsCert), SecurityAlgorithms.RsaSha256, SecurityAlgorithms.Sha256); string request = CreateMs10ATPOPAssertion( settings.ClientId, data.RequestUri.AbsoluteUri, clientCredsSigningCredentials, popKey, true); data.BodyParameters.Add("request", request); }