98 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| // ***********************************************************************
 | |
| // <copyright file="AuthExtension.cs">
 | |
| //     AgileWebs
 | |
| // </copyright>
 | |
| // ***********************************************************************
 | |
| 
 | |
| 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
 | |
| {
 | |
|     /// <summary>
 | |
|     /// Extension methods for configuring authentication with various Azure AD setups.
 | |
|     /// </summary>
 | |
|     public static class AuthenticationExtension
 | |
|     {
 | |
|         /// <summary>
 | |
|         /// Configures authentication using Azure AD for an API that requires downstream API access.
 | |
|         /// </summary>
 | |
|         /// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
 | |
|         /// <param name="configuration">The <see cref="IConfiguration"/> containing Azure AD configuration settings.</param>
 | |
|         public static void ConfigureAuthentication(this IServiceCollection services, IConfiguration configuration, AuthSettings authSettings)
 | |
|         {
 | |
|             var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty;
 | |
| 
 | |
|             var azureAdInMemorySettings = new Dictionary<string, string?>
 | |
|             {
 | |
|                 { "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<JwtIssuerOptions>();
 | |
| 
 | |
|             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<JwtIssuerOptions>(options =>
 | |
|             {
 | |
|                 options.Issuer = jwtIssuerOptions?.Issuer;
 | |
|                 options.Audience = jwtIssuerOptions?.Audience;
 | |
|                 options.SigningCredentials = new SigningCredentials(rsaPrivateKey, SecurityAlgorithms.RsaSha256);
 | |
|             });
 | |
| 
 | |
|             services.AddSingleton(jwtAppSettingOptions);
 | |
|             services.AddTransient<IAuthorizationHandler, PermissionsAuthorizationHandler>();
 | |
|             services.AddTransient<ITokenService, TokenService>();
 | |
|         }
 | |
|     }
 | |
| }
 | 
