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())
.AddInMemoryClients(IdentityContext.GetClients())
// .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();
}
}
}