Core.Thalos.BuildingBlocks/Core.Cerberos.Adapters/Extensions/AuthenticationExtension.cs
Sergio Matias Urquin d5925a6476 Add project files.
2025-04-29 18:57:20 -06:00

98 lines
4.5 KiB
C#

// ***********************************************************************
// <copyright file="AuthExtension.cs">
// Heath
// </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>();
}
}
}