Files
Core.Thalos.BuildingBlocks/Core.Thalos.BuildingBlocks/Extensions/AuthenticationExtension.cs

139 lines
6.2 KiB
C#

// ***********************************************************************
// <copyright file="AuthExtension.cs">
// AgileWebs
// </copyright>
// ***********************************************************************
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.Identity.Web;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
namespace Core.Thalos.BuildingBlocks.Configuration
{
/// <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 identityProviders = new IdentityProviders();
configuration.GetSection("IdentityProviders").Bind(identityProviders);
AddCustomAuthentication(services, authSettings.Token);
if (identityProviders.Azure)
AddAzureAuthentication(authSettings, configuration, services);
if (identityProviders.Google)
AddGoogleAuthentication(services, authSettings.Google);
services.AddAuthorization();
services.AddTransient<IAuthorizationHandler, PermissionsAuthorizationHandler>();
services.AddTransient<ITokenService, TokenService>();
}
public static void AddCustomAuthentication(IServiceCollection services, TokenAuthSettings tokenAuthSettings)
{
var rsa = RSA.Create();
rsa.ImportFromPem(tokenAuthSettings.PrivateKey?.ToCharArray());
var rsaPrivateKey = new RsaSecurityKey(rsa);
var rsaPublic = RSA.Create();
rsaPublic.ImportFromPem(tokenAuthSettings.PublicKey?.ToCharArray());
var rsaPublicKey = new RsaSecurityKey(rsaPublic);
var jwtIssuerOptions = new JwtIssuerOptions
{
Audience = tokenAuthSettings.Audience,
Issuer = tokenAuthSettings.Issuer,
};
if (string.IsNullOrEmpty(jwtIssuerOptions?.Issuer) || string.IsNullOrEmpty(jwtIssuerOptions.Audience))
throw new InvalidOperationException("JwtIssuerOptions are not configured correctly.");
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(Schemes.DefaultScheme, 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<IOptions<JwtIssuerOptions>>(Microsoft.Extensions.Options.Options.Create(jwtIssuerOptions));
}
public static void AddAzureAuthentication(AuthSettings authSettings, IConfiguration configuration, IServiceCollection services)
{
var azureAdInMemorySettings = new Dictionary<string, string?>
{
{ "AzureAdB2C:Instance", authSettings.Azure.Instance ?? string.Empty },
{ "AzureAdB2C:TenantId", authSettings.Azure.TenantId ?? string.Empty },
{ "AzureAdB2C:ClientId", authSettings.Azure.ClientId ?? string.Empty },
{ "AzureAdB2C:ClientSecret", authSettings.Azure.ClientSecret ?? 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();
}
public static void AddGoogleAuthentication(IServiceCollection services, GoogleAuthSettings googleAuthSettings)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = Schemes.GoogleScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddScheme<AuthenticationSchemeOptions,
GoogleAccessTokenAuthenticationHandler>(Schemes.GoogleScheme, null)
.AddGoogle(options =>
{
options.ClientId = googleAuthSettings.ClientId!;
options.ClientSecret = googleAuthSettings.ClientSecret!;
//options.SaveTokens = true;
options.CallbackPath = $"/{googleAuthSettings.RedirectUri}";
});
services.AddScoped<IGoogleAuthHelper, GoogleAuthHelper>();
services.AddScoped<IGoogleAuthorization, GoogleAuthorization>();
}
}
}