using System.Security.Claims; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moonlight.Api.Configuration; using Moonlight.Api.Implementations; using Moonlight.Api.Implementations.ApiKeyScheme; using Moonlight.Api.Services; namespace Moonlight.Api.Startup; public partial class Startup { private static void AddAuth(WebApplicationBuilder builder) { var oidcOptions = new OidcOptions(); builder.Configuration.GetSection("Moonlight:Oidc").Bind(oidcOptions); var apiKeyOptions = new ApiOptions(); builder.Configuration.GetSection("Moonlight:Api").Bind(apiKeyOptions); builder.Services.AddOptions().BindConfiguration("Moonlight:Api"); builder.Services.AddScoped(); builder.Services.AddAuthentication("Main") .AddPolicyScheme("Main", null, options => { options.ForwardDefaultSelector += context => context.Request.Headers.Authorization.Count > 0 ? "ApiKey" : "Session"; }) .AddCookie("Session", null, options => { options.Events.OnSigningIn += async context => { var authService = context .HttpContext .RequestServices .GetRequiredService(); var result = await authService.SyncAsync(context.Principal); if (result) context.Properties.IsPersistent = true; else context.Principal = new ClaimsPrincipal(); }; options.Events.OnValidatePrincipal += async context => { var authService = context .HttpContext .RequestServices .GetRequiredService(); var result = await authService.ValidateAsync(context.Principal); if (!result) context.RejectPrincipal(); }; options.Cookie = new CookieBuilder() { Name = "token", Path = "/", IsEssential = true, SecurePolicy = CookieSecurePolicy.SameAsRequest }; }) .AddOpenIdConnect("OIDC", "OpenID Connect", options => { options.Authority = oidcOptions.Authority; options.RequireHttpsMetadata = oidcOptions.RequireHttpsMetadata; var scopes = oidcOptions.Scopes ?? ["openid", "email", "profile"]; options.Scope.Clear(); foreach (var scope in scopes) options.Scope.Add(scope); options.ResponseType = oidcOptions.ResponseType; options.ClientId = oidcOptions.ClientId; options.ClientSecret = oidcOptions.ClientSecret; options.ClaimActions.MapJsonKey(ClaimTypes.Name, "name"); options.ClaimActions.MapJsonKey(ClaimTypes.Name, "preferred_username"); options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email"); options.GetClaimsFromUserInfoEndpoint = true; }) .AddScheme("ApiKey", null, options => { options.LookupCacheTime = TimeSpan.FromMinutes(apiKeyOptions.LookupCacheMinutes); }); builder.Logging.AddFilter("Moonlight.Api.Implementations.ApiKeyScheme.ApiKeySchemeHandler", LogLevel.Warning); builder.Services.AddSingleton(); builder.Services.AddSingleton(); } private static void UseAuth(WebApplication application) { application.UseAuthentication(); application.UseAuthorization(); } }