// *********************************************************************** // // AgileWebs // // *********************************************************************** using Core.Cerberos.Adapters.Common.Constants; using Core.Cerberos.Adapters.Contracts; using Core.Cerberos.Adapters.Handlers; using Core.Cerberos.Adapters.Options; using Core.Cerberos.Adapters.Services; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Identity.Web; using Microsoft.IdentityModel.Tokens; using System.Security.Cryptography; namespace Core.Cerberos.Adapters.Extensions { /// /// Extension methods for configuring authentication with various Azure AD setups. /// public static class AuthenticationExtension { /// /// Configures authentication using Azure AD for an API that requires downstream API access. /// /// The to add the services to. /// The containing Azure AD configuration settings. public static void ConfigureAuthentication(this IServiceCollection services, IConfiguration configuration, AuthSettings authSettings) { var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; var azureAdInMemorySettings = new Dictionary { { "AzureAdB2C:Instance", authSettings.AzureADInstance ?? string.Empty }, { "AzureAdB2C:TenantId", authSettings.AzureADTenantId ?? string.Empty }, { "AzureAdB2C:ClientId", authSettings.AzureADClientId ?? string.Empty }, { "AzureAdB2C:ClientSecret", authSettings.AzureADClientSecret ?? string.Empty } }; var configurationBuilder = new ConfigurationBuilder() .AddConfiguration(configuration) .AddInMemoryCollection(azureAdInMemorySettings); var combinedConfiguration = configurationBuilder.Build(); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(combinedConfiguration.GetSection("AzureAdB2C"), Schemes.AzureScheme) .EnableTokenAcquisitionToCallDownstreamApi() .AddMicrosoftGraph(configuration.GetSection("MicrosoftGraph")) .AddInMemoryTokenCaches(); var rsa = RSA.Create(); rsa.ImportFromPem(authSettings.PrivateKey?.ToCharArray()); var rsaPrivateKey = new RsaSecurityKey(rsa); var rsaPublic = RSA.Create(); rsaPublic.ImportFromPem(authSettings.PublicKey?.ToCharArray()); var rsaPublicKey = new RsaSecurityKey(rsaPublic); var jwtAppSettingOptions = configuration.GetSection("B2C:JwtIssuerOptions"); var jwtIssuerOptions = jwtAppSettingOptions.Get(); if (string.IsNullOrEmpty(jwtIssuerOptions?.Issuer) || string.IsNullOrEmpty(jwtIssuerOptions.Audience)) throw new InvalidOperationException("JwtIssuerOptions are not configured correctly."); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(Schemes.HeathScheme, x => { x.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = jwtIssuerOptions?.Issuer, ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidAudience = jwtIssuerOptions?.Audience, IssuerSigningKey = rsaPublicKey }; }); services.Configure(options => { options.Issuer = jwtIssuerOptions?.Issuer; options.Audience = jwtIssuerOptions?.Audience; options.SigningCredentials = new SigningCredentials(rsaPrivateKey, SecurityAlgorithms.RsaSha256); }); services.AddSingleton(jwtAppSettingOptions); services.AddTransient(); services.AddTransient(); } } }