private static void RegisterAuthenticationServicesWithCertificate( IServiceCollection services, IConfiguration configuration, AuthenticationOptions authenticationOptions, AzureADOptions azureADOptions) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi( options => { options.Authority = $"{azureADOptions.Instance}{azureADOptions.TenantId}/v2.0"; options.SaveToken = true; options.TokenValidationParameters.ValidAudiences = AuthenticationServiceCollectionExtensions.GetValidAudiences(authenticationOptions); options.TokenValidationParameters.AudienceValidator = AuthenticationServiceCollectionExtensions.AudienceValidator; options.TokenValidationParameters.ValidIssuers = AuthenticationServiceCollectionExtensions.GetValidIssuers(authenticationOptions); }, microsoftIdentityOptions => { configuration.Bind("AzureAd", microsoftIdentityOptions); microsoftIdentityOptions.ClientCertificates = new CertificateDescription[] { CertificateDescription.FromKeyVault(configuration.GetValue <string>("KeyVault:Url"), configuration.GetValue <string>("GraphAppCertName")), }; }) .EnableTokenAcquisitionToCallDownstreamApi( confidentialClientApplicationOptions => { configuration.Bind("AzureAd", confidentialClientApplicationOptions); }) .AddInMemoryTokenCaches(); }
public void TestFromKeyVault(string keyVaultUrl, string certificateName) { CertificateDescription certificateDescription = CertificateDescription.FromKeyVault(keyVaultUrl, certificateName); Assert.Equal(CertificateSource.KeyVault, certificateDescription.SourceType); Assert.Equal(keyVaultUrl, certificateDescription.Container); Assert.Equal(certificateName, certificateDescription.ReferenceOrValue); Assert.Equal(certificateName, certificateDescription.KeyVaultCertificateName); Assert.Equal(keyVaultUrl, certificateDescription.KeyVaultUrl); }
public void TestFromKeyVault(string keyVaultUrl, string certificateName) { CertificateDescription certificateDescription = CertificateDescription.FromKeyVault(keyVaultUrl, certificateName); Assert.Equal(CertificateSource.KeyVault, certificateDescription.SourceType); Assert.Equal(keyVaultUrl, certificateDescription.Container); Assert.Equal(certificateName, certificateDescription.ReferenceOrValue); Assert.Equal(certificateName, certificateDescription.KeyVaultCertificateName); Assert.Equal(keyVaultUrl, certificateDescription.KeyVaultUrl); Assert.Equal(X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet, certificateDescription.X509KeyStorageFlags); certificateDescription.X509KeyStorageFlags = X509KeyStorageFlags.UserKeySet; Assert.Equal(X509KeyStorageFlags.UserKeySet, certificateDescription.X509KeyStorageFlags); }
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); }
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); }