public void TestLoadAllCertificates(
            CertificateSource certificateSource,
            string container,
            string referenceOrValue)
        {
            List <CertificateDescription> certDescriptions = CreateCertificateDescriptions(
                certificateSource,
                container,
                referenceOrValue).ToList();

            certDescriptions.Add(new CertificateDescription
            {
                SourceType       = certificateSource,
                Container        = container,
                ReferenceOrValue = referenceOrValue,
            });

            certDescriptions.Add(CertificateDescription.FromCertificate(null));

            IEnumerable <X509Certificate2> certificates = DefaultCertificateLoader.LoadAllCertificates(certDescriptions);

            Assert.NotNull(certificates);
            Assert.Equal(2, certificates.Count());
            Assert.Equal(3, certDescriptions.Count);
            Assert.Equal("CN=ACS2ClientCertificate", certificates.First().Issuer);
            Assert.Equal("CN=ACS2ClientCertificate", certificates.Last().Issuer);
            Assert.Null(certDescriptions.ElementAt(2).Certificate);
        }
예제 #2
0
        private static async Task RunAsync()
        {
            AuthenticationConfig config = AuthenticationConfig.ReadFromJsonFile("appsettings.json");

            // Load the certificate
            ICertificateLoader certificateLoader = new DefaultCertificateLoader();

            certificateLoader.LoadIfNeeded(config.Certificate);

            // Even if this is a console application here, a daemon application is a confidential client application
            IConfidentialClientApplication app;

            app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
                  .WithCertificate(config.Certificate.Certificate)
                  .WithAuthority(new Uri(config.Authority))
                  .Build();

            // With client credentials flows the scopes is ALWAYS of the shape "resource/.default", as the
            // application permissions need to be set statically (in the portal or by PowerShell), and then granted by
            // a tenant administrator.
            string[] scopes = new string[] { $"{config.ApiUrl}.default" };

            AuthenticationResult result = null;

            try
            {
                result = await app.AcquireTokenForClient(scopes)
                         .ExecuteAsync();

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Token acquired");
                Console.ResetColor();
            }
            catch (MsalServiceException ex) when(ex.Message.Contains("AADSTS70011"))
            {
                // Invalid scope. The scope has to be of the form "https://resourceurl/.default"
                // Mitigation: change the scope to be as expected
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Scope provided is not supported");
                Console.ResetColor();
            }

            if (result != null)
            {
                var httpClient = new HttpClient();
                var apiCaller  = new ProtectedApiCallHelper(httpClient);
                await apiCaller.CallWebApiAndProcessResultASync($"{config.ApiUrl}v1.0/users", result.AccessToken, Display);
            }
        }
        public void TestLoadFirstCertificate(
            CertificateSource certificateSource,
            string container,
            string referenceOrValue)
        {
            IEnumerable <CertificateDescription> certDescriptions = CreateCertificateDescriptions(
                certificateSource,
                container,
                referenceOrValue);

            X509Certificate2 certificate = DefaultCertificateLoader.LoadFirstCertificate(certDescriptions);

            Assert.NotNull(certificate);
            Assert.Equal("CN=ACS2ClientCertificate", certificate.Issuer);
        }
        public void TestDefaultCertificateLoader(CertificateSource certificateSource, string container, string referenceOrValue)
        {
            CertificateDescription certificateDescription;

            switch (certificateSource)
            {
            case CertificateSource.KeyVault:
                certificateDescription = CertificateDescription.FromKeyVault(container, referenceOrValue);
                break;

            case CertificateSource.Base64Encoded:
                certificateDescription = CertificateDescription.FromBase64Encoded(referenceOrValue);
                break;

            case CertificateSource.Path:
                certificateDescription = CertificateDescription.FromPath(container, referenceOrValue);
                break;

            case CertificateSource.StoreWithThumbprint:
                certificateDescription = new CertificateDescription()
                {
                    SourceType = CertificateSource.StoreWithThumbprint
                };
                certificateDescription.CertificateThumbprint = referenceOrValue;
                certificateDescription.CertificateStorePath  = container;
                break;

            case CertificateSource.StoreWithDistinguishedName:
                certificateDescription = new CertificateDescription()
                {
                    SourceType = CertificateSource.StoreWithDistinguishedName
                };
                certificateDescription.CertificateDistinguishedName = referenceOrValue;
                certificateDescription.CertificateStorePath         = container;
                break;

            default:
                certificateDescription = null;
                break;
            }

            ICertificateLoader loader = new DefaultCertificateLoader();

            loader.LoadIfNeeded(certificateDescription);

            Assert.NotNull(certificateDescription.Certificate);
        }
예제 #5
0
        private static async Task RunAsync()
        {
            AuthenticationConfig config = AuthenticationConfig.ReadFromJsonFile("appsettings.json");

            // You can run this sample using ClientSecret or Certificate. The code will differ only when instantiating the IConfidentialClientApplication
            bool isUsingClientSecret = IsAppUsingClientSecret(config);

            // Even if this is a console application here, a daemon application is a confidential client application
            IConfidentialClientApplication app;

            if (isUsingClientSecret)
            {
                // Even if this is a console application here, a daemon application is a confidential client application
                app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
                      .WithClientSecret(config.ClientSecret)
                      .WithAuthority(new Uri(config.Authority))
                      .Build();
            }

            else
            {
                ICertificateLoader certificateLoader = new DefaultCertificateLoader();
                certificateLoader.LoadIfNeeded(config.Certificate);

                app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
                      .WithCertificate(config.Certificate.Certificate)
                      .WithAuthority(new Uri(config.Authority))
                      .Build();
            }

            app.AddInMemoryTokenCache();

            // With client credentials flows the scopes is ALWAYS of the shape "resource/.default", as the
            // application permissions need to be set statically (in the portal or by PowerShell), and then granted by
            // a tenant administrator.
            string[] scopes = new string[] { $"{config.ApiUrl}.default" }; // Generates a scope -> "https://graph.microsoft.com/.default"

            // Call MS graph using the Graph SDK
            await CallMSGraphUsingGraphSDK(app, scopes);

            // Call MS Graph REST API directly
            await CallMSGraph(config, app, scopes);
        }
        static async Task Main(string[] args)
        {
            string clientId = "6af093f3-b445-4b7a-beae-046864468ad6";
            string tenant   = "msidentitysamplestesting.onmicrosoft.com";

            string[] scopes = new[] { "api://8206b76f-586e-4098-b1e5-598c1aa3e2a1/.default" };

            // Simulates the configuration, could be a IConfiguration or anything
            Dictionary <string, string> Configuration = new Dictionary <string, string>();

            // Certificate Loading
            string keyVaultContainer = "https://WebAppsApisTests.vault.azure.net";
            string keyVaultReference = "Self-Signed-5-5-22";
            CertificateDescription certDescription   = CertificateDescription.FromKeyVault(keyVaultContainer, keyVaultReference);
            ICertificateLoader     certificateLoader = new DefaultCertificateLoader();

            certificateLoader.LoadIfNeeded(certDescription);

            // Create the confidential client application
            IConfidentialClientApplication app;

            app = ConfidentialClientApplicationBuilder.Create(clientId)
                  // Alternatively to the certificate you can use .WithClientSecret(clientSecret)
                  .WithCertificate(certDescription.Certificate)
                  .WithTenantId(tenant)
                  .Build();

            //  In memory token caches (App and User caches)
            // app.AddInMemoryTokenCache();

            // Or

            // Distributed token caches (App and User caches)
            // Add one of the below: SQL, Redis, CosmosDb
            app.AddDistributedTokenCache(services =>
            {
                services.AddDistributedMemoryCache();
                services.AddLogging(configure => configure.AddConsole())
                .Configure <LoggerFilterOptions>(options => options.MinLevel = Microsoft.Extensions.Logging.LogLevel.Debug);

                /* Remove comments to use SQL cache implementation
                 * services.AddDistributedSqlServerCache(options =>
                 * {
                 *  // SQL Server token cache
                 *  // Requires to reference Microsoft.Extensions.Caching.SqlServer
                 *  options.ConnectionString = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=TestCache;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";
                 *  options.SchemaName = "dbo";
                 *  options.TableName = "TestCache";
                 *
                 *  // You don't want the SQL token cache to be purged before the access token has expired. Usually
                 *  // access tokens expire after 1 hour (but this can be changed by token lifetime policies), whereas
                 *  // the default sliding expiration for the distributed SQL database is 20 mins.
                 *  // Use a value which is above 60 mins (or the lifetime of a token in case of longer lived tokens)
                 *  options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
                 * });
                 */

                /* Remove comments to use Redis cache implementation
                 * // Add Redis
                 * services.AddStackExchangeRedisCache(options =>
                 * {
                 *  options.Configuration = "localhost";
                 *  options.InstanceName = "Redis";
                 * });
                 */

                /* Remove comments to use CosmosDB cache implementation
                 * // Add CosmosDB
                 * services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
                 * {
                 *  cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
                 *  cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
                 *  cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
                 *  cacheOptions.CreateIfNotExists = true;
                 * });
                 */
            });

            // Acquire a token (twice)
            var result = await app.AcquireTokenForClient(scopes)
                         .ExecuteAsync();

            Console.WriteLine(result.AuthenticationResultMetadata.TokenSource);

            result = await app.AcquireTokenForClient(scopes)
                     .ExecuteAsync();

            Console.WriteLine(result.AuthenticationResultMetadata.TokenSource);
        }