139 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			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>();
 | |
|         }
 | |
|     }
 | |
| }
 |