Files
git.stella-ops.org/inspiration/Ablera.Serdica.Authentication/DependencyInjection/ServiceCollectionExtensions.cs
root df5984d07e
Some checks failed
Build Test Deploy / build-test (push) Has been cancelled
Build Test Deploy / authority-container (push) Has been cancelled
Build Test Deploy / docs (push) Has been cancelled
Build Test Deploy / deploy (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
up
2025-10-10 06:53:40 +00:00

130 lines
5.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Validation.AspNetCore;
using OpenIddict.Validation.SystemNetHttp;
using StackExchange.Redis;
using Ablera.Serdica.Authentication.Models;
using Ablera.Serdica.Authentication.Models.Oidc;
using Ablera.Serdica.Authentication.Utilities;
using Microsoft.AspNetCore.DataProtection;
using Ablera.Serdica.Authentication.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Ablera.Serdica.Authentication.Constants;
using OpenIddict.Client;
using OpenIddict.Validation;
using System.Linq;
using System.Collections.Generic;
using System.Security.Claims;
using Microsoft.AspNetCore.Identity;
using System.Security.Principal;
using OpenIddict.Client.AspNetCore;
using Microsoft.AspNetCore.Authorization;
using Ablera.Serdica.DependencyInjection;
using static Ablera.Serdica.Authentication.Constants.ConstantsClass;
using static OpenIddict.Abstractions.OpenIddictConstants;
using System.IdentityModel.Tokens.Jwt;
using static OpenIddict.Client.OpenIddictClientEvents;
namespace Ablera.Serdica.DependencyInjection;
public sealed class AcceptAnyIssuer :
IOpenIddictClientHandler<OpenIddict.Client.OpenIddictClientEvents.HandleConfigurationResponseContext>
{
public ValueTask HandleAsync(HandleConfigurationResponseContext ctx)
{
// Short-circuit the built-in ValidateIssuer handler.
ctx.SkipRequest();
return default;
}
}
public static class JwtBearerWithSessionAuthenticationExtensions
{
public static IServiceCollection AddDataProtection(this IServiceCollection services, IConfiguration configuration)
{
//------------------------------------------------------------------
// 1) read configuration
//------------------------------------------------------------------
var redisConfiguration = RedisConfigurationGetter.GetRedisConfiguration(configuration);
var multiplexer = ConnectionMultiplexer.Connect(redisConfiguration);
services.AddSingleton<IConnectionMultiplexer>(multiplexer);
//------------------------------------------------------------------
// 2) Data-Protection (encrypt/sign cookies) keys stored in Redis
//------------------------------------------------------------------
var xmlRepo = new RedisAndFileSystemXmlRepository(
multiplexer.GetDatabase(), RedisKeyPrefixKey);
services.AddDataProtection()
.SetApplicationName(DataProtectionApplicationName)
.PersistKeysToStackExchangeRedis(multiplexer, RedisKeyPrefixKey)
.AddKeyManagementOptions(o => o.XmlRepository = xmlRepo)
.SetDefaultKeyLifetime(TimeSpan.FromDays(30));
return services;
}
public static IServiceCollection AddMicroserviceAuthentication(
this IServiceCollection services,
IConfiguration cfg,
IHostEnvironment env)
{
// ---------------------------------------------------------------------
// 1) Read and validate the OIDC client settings
// ---------------------------------------------------------------------
var oidc = cfg.GetSection(nameof(OidcValidation)).Get<OidcValidation>()
?? throw new InvalidOperationException($"{nameof(OidcValidation)} section is missing.");
if (string.IsNullOrWhiteSpace(oidc.EncryptionKey))
throw new InvalidOperationException($"{nameof(oidc.EncryptionKey)} is not defined.");
// Issuer value found in the `iss` claim of the tokens (HTTPS as issued by the IdP)
var issuerUrl = new Uri(oidc.IssuerUrl
?? throw new InvalidOperationException($"{nameof(oidc.IssuerUrl)} is not defined."));
services.Configure<OidcValidation>(cfg.GetSection(nameof(OidcValidation)));
services
.AddDataProtection(cfg)
.AddOpenIddict()
.AddValidation(opt =>
{
opt.UseSystemNetHttp();
opt.UseAspNetCore();
opt.SetIssuer(issuerUrl);
if (!string.IsNullOrWhiteSpace(oidc.ConfigurationUrl))
{
opt.Configure(x =>
{
x.ConfigurationEndpoint = new Uri(oidc.ConfigurationUrl);
});
}
opt.AddEncryptionKey(
new SymmetricSecurityKey(Convert.FromBase64String(oidc.EncryptionKey)));
});
services.AddAuthorization(options =>
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build())
.AddAuthentication(options =>
{
options.DefaultScheme = ConstantsClass.AuthenticationScheme;
options.DefaultChallengeScheme = ConstantsClass.AuthenticationScheme;
})
.AddScheme<JwtBearerOptions, SerdicaJwtBearerAuthenticationHandler>(
ConstantsClass.AuthenticationScheme, _ => { });
return services;
}
}