using System; using System.Collections.Generic; using IdentityServer4.Extensions; using IdentityServer4.Services; using Kyoo.Authentication.Models; using Kyoo.Controllers; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Kyoo.Authentication { /// /// A module that enable OpenID authentication for Kyoo. /// public class AuthenticationModule : IPlugin { /// public string Slug => "auth"; /// public string Name => "Authentication"; /// public string Description => "Enable OpenID authentication for Kyoo."; /// public ICollection Provides => ArraySegment.Empty; /// public ICollection ConditionalProvides => ArraySegment.Empty; /// public ICollection Requires => ArraySegment.Empty; /// /// The configuration to use. /// private readonly IConfiguration _configuration; /// /// A logger factory to allow IdentityServer to log things. /// private readonly ILoggerFactory _loggerFactory; /// /// Create a new authentication module instance and use the given configuration and environment. /// /// The configuration to use /// The logger factory to allow IdentityServer to log things public AuthenticationModule(IConfiguration configuration, ILoggerFactory loggerFactory) { _configuration = configuration; _loggerFactory = loggerFactory; } /// public IServiceCollection Configure(IServiceCollection services, ICollection availableTypes) { string publicUrl = _configuration.GetValue("public_url"); // services.AddDbContext(options => // { // options.UseNpgsql(_configuration.GetDatabaseConnection("postgres")); // }); // services.AddIdentityCore(o => // { // o.Stores.MaxLengthForKeys = 128; // }) // .AddSignInManager() // .AddDefaultTokenProviders() // .AddEntityFrameworkStores(); CertificateOption certificateOptions = new(); _configuration.GetSection(CertificateOption.Path).Bind(certificateOptions); services.AddIdentityServer(options => { options.IssuerUri = publicUrl; options.UserInteraction.LoginUrl = publicUrl + "login"; options.UserInteraction.ErrorUrl = publicUrl + "error"; options.UserInteraction.LogoutUrl = publicUrl + "logout"; }) // .AddAspNetIdentity() // .AddConfigurationStore(options => // { // options.ConfigureDbContext = builder => // builder.UseNpgsql(_configuration.GetDatabaseConnection("postgres"), // sql => sql.MigrationsAssembly(assemblyName)); // }) // .AddOperationalStore(options => // { // options.ConfigureDbContext = builder => // builder.UseNpgsql(_configuration.GetDatabaseConnection("postgres"), // sql => sql.MigrationsAssembly(assemblyName)); // options.EnableTokenCleanup = true; // }) .AddInMemoryIdentityResources(IdentityContext.GetIdentityResources()) .AddInMemoryApiScopes(IdentityContext.GetScopes()) .AddInMemoryApiResources(IdentityContext.GetApis()) // .AddProfileService() .AddSigninKeys(certificateOptions); services.AddAuthentication(o => { o.DefaultScheme = IdentityConstants.ApplicationScheme; o.DefaultSignInScheme = IdentityConstants.ExternalScheme; }) .AddIdentityCookies(_ => { }); services.AddAuthentication() .AddJwtBearer(options => { options.Authority = publicUrl; options.Audience = "Kyoo"; options.RequireHttpsMetadata = false; }); services.AddAuthorization(options => { AuthorizationPolicyBuilder scheme = new(IdentityConstants.ApplicationScheme, JwtBearerDefaults.AuthenticationScheme); options.DefaultPolicy = scheme.RequireAuthenticatedUser().Build(); string[] permissions = {"Read", "Write", "Play", "Admin"}; foreach (string permission in permissions) { options.AddPolicy(permission, policy => { policy.AuthenticationSchemes.Add(IdentityConstants.ApplicationScheme); policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); policy.AddRequirements(new AuthorizationValidator(permission)); policy.RequireScope($"kyoo.{permission.ToLower()}"); }); } }); services.AddSingleton(); DefaultCorsPolicyService cors = new(_loggerFactory.CreateLogger()) { AllowedOrigins = {new Uri(publicUrl).GetLeftPart(UriPartial.Authority)} }; services.AddSingleton(cors); return services; } /// public void ConfigureAspNet(IApplicationBuilder app) { app.UseAuthorization(); app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Strict }); app.UseAuthentication(); app.Use((ctx, next) => { ctx.SetIdentityServerOrigin(_configuration.GetValue("public_url")); return next(); }); app.UseIdentityServer(); } } }