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));
        }
Example #3
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);
        }
        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" }
            });
        }
Example #5
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);
        }
        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);
        }
Example #7
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();
            }
        }
        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);
        }