Example #1
0
        [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));
        }
Example #5
0
        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);
        }
Example #7
0
        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);
        }
Example #9
0
        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);
        }
Example #10
0
        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();
            }
        }
Example #11
0
        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");
        }
Example #12
0
        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");
        }