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
130 lines
5.5 KiB
C#
130 lines
5.5 KiB
C#
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;
|
||
}
|
||
|
||
} |