[Ignore] //See https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/2781 public async Task InvalidRegion_GoesToInvalidAuthority_Async() { // Arrange var factory = new HttpSnifferClientFactory(); var settings = ConfidentialAppSettings.GetSettings(Cloud.Public); _confidentialClientApplication = BuildCCA(settings, factory, true, "invalid"); Environment.SetEnvironmentVariable(TestConstants.RegionName, TestConstants.Region); AuthenticationResult result = await GetAuthenticationResultAsync(settings.AppScopes).ConfigureAwait(false); // regional endpoint AssertTokenSourceIsIdp(result); Assert.AreEqual( "https://invalid.login.microsoft.com/72f988bf-86f1-41af-91ab-2d7cd011db47/oauth2/v2.0/token?allowestsrnonmsi=true", factory.RequestsAndResponses.Single().Item1.RequestUri.ToString()); AssertTelemetry(factory, $"{TelemetryConstants.HttpTelemetrySchemaVersion}|1004,{CacheInfoTelemetry.NoCachedAT:D},invalid,3,3|0,1"); _confidentialClientApplication = BuildCCA(settings, factory, true, TestConstants.Region); result = await GetAuthenticationResultAsync(settings.AppScopes, withForceRefresh : true).ConfigureAwait(false); // regional endpoint AssertTokenSourceIsIdp(result); AssertValidHost(true, factory, 1); AssertTelemetry(factory, $"{TelemetryConstants.HttpTelemetrySchemaVersion}|1004,{CacheInfoTelemetry.ForceRefresh:D},centralus,2,1|0,1", 1); }
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)); }
public static void Main(string[] args) { var ccaSettings = ConfidentialAppSettings.GetSettings(Cloud.Public); s_clientIdForConfidentialApp = ccaSettings.ClientId; s_ccaAuthority = ccaSettings.Authority; s_confidentialClientSecret = ccaSettings.GetSecret(); var pca = CreatePca(); RunConsoleAppLogicAsync(pca).Wait(); }
private static string GetSignedClientAssertionUsingMsalInternal(string clientId, IDictionary <string, string> claims) { #if NET_CORE var manager = new Client.Platforms.netcore.NetCoreCryptographyManager(); #else var manager = new Client.Platforms.net45.NetDesktopCryptographyManager(); #endif var jwtToken = new Client.Internal.JsonWebToken(manager, clientId, TestConstants.ClientCredentialAudience, claims); var cert = ConfidentialAppSettings.GetSettings(Cloud.Public).GetCertificate(); return(jwtToken.Sign(cert, Base64UrlHelpers.Encode(cert.GetCertHash()), true)); }
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); }
public async Task InvalidRegion_GoesToInvalidAuthority_Async() { // Arrange var factory = new HttpSnifferClientFactory(); var settings = ConfidentialAppSettings.GetSettings(Cloud.Public); _confidentialClientApplication = BuildCCA(settings, factory, true, "invalid"); Environment.SetEnvironmentVariable(TestConstants.RegionName, TestConstants.Region); var ex = await Assert.ThrowsExceptionAsync <HttpRequestException>( async() => await GetAuthenticationResultAsync(settings.AppScopes).ConfigureAwait(false)).ConfigureAwait(false); Assert.IsTrue(ex is HttpRequestException); }
public async Task AcquireTokenToRegionalEndpointAsync() { // Arrange var factory = new HttpSnifferClientFactory(); var settings = ConfidentialAppSettings.GetSettings(Cloud.Public); _confidentialClientApplication = BuildCCA(settings, factory); Environment.SetEnvironmentVariable(TestConstants.RegionName, TestConstants.Region); AuthenticationResult result = await GetAuthenticationResultAsync(settings.AppScopes).ConfigureAwait(false); // regional endpoint AssertTokenSourceIsIdp(result); AssertValidHost(true, factory); AssertTelemetry(factory, $"{TelemetryConstants.HttpTelemetrySchemaVersion}|1004,{CacheInfoTelemetry.NoCachedAT:D},centralus,3,4|0,1"); }
public async Task AcquireTokenToRegionalEndpointAsync() { // Arrange var factory = new HttpSnifferClientFactory(); var settings = ConfidentialAppSettings.GetSettings(Cloud.Public); _confidentialClientApplication = BuildCCA(settings, factory); Environment.SetEnvironmentVariable(TestConstants.RegionName, TestConstants.Region); AuthenticationResult result = await GetAuthenticationResultAsync(settings.AppScopes).ConfigureAwait(false); // regional endpoint AssertTokenSourceIsIdp(result); AssertValidHost(true, factory); AssertTelemetry(factory, $"{TelemetryConstants.HttpTelemetrySchemaVersion}|1004,{CacheRefreshReason.NoCachedAccessToken:D},centralus,3,4|0,1"); Assert.AreEqual( $"https://centralus.r.login.microsoftonline.com/{settings.TenantId}/oauth2/v2.0/token", result.AuthenticationResultMetadata.TokenEndpoint); }
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); }
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(); } }
public async Task ServicePrincipal_OBO_PPE_Async() { //An explanation of the OBO for service principal scenario can be found here https://aadwiki.windows-int.net/index.php?title=App_OBO_aka._Service_Principal_OBO var settings = ConfidentialAppSettings.GetSettings(Cloud.Public); var cert = settings.GetCertificate(); IReadOnlyList <string> middleTierApiScopes = new List <string>() { OBOServicePpeClientID + "/.default" }; IReadOnlyList <string> downstreamApiScopes = new List <string>() { OBOServiceDownStreamApiPpeClientID + "/.default" }; var clientConfidentialApp = ConfidentialClientApplicationBuilder .Create(OBOClientPpeClientID) .WithAuthority(PPEAuthenticationAuthority) .WithCertificate(cert) .WithTestLogging() .Build(); var authenticationResult = await clientConfidentialApp .AcquireTokenForClient(middleTierApiScopes) .ExecuteAsync() .ConfigureAwait(false); string appToken = authenticationResult.AccessToken; var userAssertion = new UserAssertion(appToken); string atHash = userAssertion.AssertionHash; var middletierServiceApp = ConfidentialClientApplicationBuilder .Create(OBOServicePpeClientID) .WithAuthority(PPEAuthenticationAuthority) .WithCertificate(cert) .Build(); var userCacheRecorder = middletierServiceApp.UserTokenCache.RecordAccess(); authenticationResult = await middletierServiceApp .AcquireTokenOnBehalfOf(downstreamApiScopes, userAssertion) .ExecuteAsync() .ConfigureAwait(false); Assert.IsNotNull(authenticationResult.AccessToken); Assert.IsFalse(userCacheRecorder.LastAfterAccessNotificationArgs.IsApplicationCache); Assert.IsTrue(userCacheRecorder.LastAfterAccessNotificationArgs.HasTokens); Assert.AreEqual(atHash, userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey); Assert.AreEqual(TokenSource.IdentityProvider, authenticationResult.AuthenticationResultMetadata.TokenSource); Assert.IsNotNull( userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheExpiry, "When writing the OBO token response, MSAL should ignore the RT and propose expiry"); authenticationResult = await middletierServiceApp .AcquireTokenOnBehalfOf(downstreamApiScopes, userAssertion) .ExecuteAsync() .ConfigureAwait(false); Assert.IsNotNull(authenticationResult.AccessToken); Assert.IsTrue(!userCacheRecorder.LastAfterAccessNotificationArgs.IsApplicationCache); Assert.IsTrue(userCacheRecorder.LastAfterAccessNotificationArgs.HasTokens); Assert.AreEqual(atHash, userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey); Assert.AreEqual(TokenSource.Cache, authenticationResult.AuthenticationResultMetadata.TokenSource); Assert.IsNull( userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheExpiry, "The cache expiry is not set because the node did not change"); }
public async Task ServicePrincipal_OBO_LongRunningProcess_PPE_Async() { //An explanation of the OBO for service principal scenario can be found here https://aadwiki.windows-int.net/index.php?title=App_OBO_aka._Service_Principal_OBO var settings = ConfidentialAppSettings.GetSettings(Cloud.Public); var cert = settings.GetCertificate(); IReadOnlyList <string> middleTierApiScopes = new List <string>() { OBOServicePpeClientID + "/.default" }; IReadOnlyList <string> downstreamApiScopes = new List <string>() { OBOServiceDownStreamApiPpeClientID + "/.default" }; var clientConfidentialApp = ConfidentialClientApplicationBuilder .Create(OBOClientPpeClientID) .WithAuthority(PPEAuthenticationAuthority) .WithCertificate(cert) .WithTestLogging() .Build(); var middletierServiceApp = ConfidentialClientApplicationBuilder .Create(OBOServicePpeClientID) .WithAuthority(PPEAuthenticationAuthority) .WithCertificate(cert) .Build(); var userCacheRecorder = middletierServiceApp.UserTokenCache.RecordAccess(); Trace.WriteLine("1. Upstream client gets an app token"); var authenticationResult = await clientConfidentialApp .AcquireTokenForClient(middleTierApiScopes) .ExecuteAsync() .ConfigureAwait(false); string clientToken = authenticationResult.AccessToken; Trace.WriteLine("2. MidTier kicks off the long running process by getting an OBO token"); string cacheKey = null; authenticationResult = await(middletierServiceApp as ILongRunningWebApi). InitiateLongRunningProcessInWebApi(downstreamApiScopes, clientToken, ref cacheKey) .ExecuteAsync().ConfigureAwait(false); Assert.IsNotNull(authenticationResult.AccessToken); Assert.IsTrue(!userCacheRecorder.LastAfterAccessNotificationArgs.IsApplicationCache); Assert.IsTrue(userCacheRecorder.LastAfterAccessNotificationArgs.HasTokens); Assert.AreEqual(cacheKey, userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey); Assert.AreEqual(TokenSource.IdentityProvider, authenticationResult.AuthenticationResultMetadata.TokenSource); Assert.IsNull( userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheExpiry, "The cache expiry is not set because there is an RT in the cache"); Trace.WriteLine("3. Later, mid-tier needs the token again, and one is in the cache"); authenticationResult = await(middletierServiceApp as ILongRunningWebApi) .AcquireTokenInLongRunningProcess(downstreamApiScopes, cacheKey) .ExecuteAsync() .ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, authenticationResult.AuthenticationResultMetadata.TokenSource); Trace.WriteLine("4. After the original token expires, the mid-tier needs a token again. RT will be used."); TokenCacheHelper.ExpireAllAccessTokens(middletierServiceApp.UserTokenCache as ITokenCacheInternal); authenticationResult = await(middletierServiceApp as ILongRunningWebApi) .AcquireTokenInLongRunningProcess(downstreamApiScopes, cacheKey) .ExecuteAsync() .ConfigureAwait(false); Assert.IsNotNull(authenticationResult.AccessToken); Assert.IsTrue(!userCacheRecorder.LastAfterAccessNotificationArgs.IsApplicationCache); Assert.IsTrue(userCacheRecorder.LastAfterAccessNotificationArgs.HasTokens); Assert.AreEqual(cacheKey, userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey); Assert.AreEqual(TokenSource.IdentityProvider, authenticationResult.AuthenticationResultMetadata.TokenSource); Assert.IsNull( userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheExpiry, "The cache expiry is not set because there is an RT in the cache"); }