diff --git a/src/Kyoo.Authentication/AuthenticationModule.cs b/src/Kyoo.Authentication/AuthenticationModule.cs
index ee3cfdc9..604521ca 100644
--- a/src/Kyoo.Authentication/AuthenticationModule.cs
+++ b/src/Kyoo.Authentication/AuthenticationModule.cs
@@ -18,27 +18,21 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.IO;
-using System.Linq;
using System.Reflection;
+using System.Text;
using Autofac;
-using IdentityServer4.Extensions;
-using IdentityServer4.Models;
-using IdentityServer4.Services;
using Kyoo.Abstractions;
using Kyoo.Abstractions.Controllers;
using Kyoo.Authentication.Models;
-using Kyoo.Authentication.Views;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Microsoft.IdentityModel.Logging;
+using Microsoft.IdentityModel.Tokens;
using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode;
namespace Kyoo.Authentication
@@ -55,14 +49,13 @@ namespace Kyoo.Authentication
public string Name => "Authentication";
///
- public string Description => "Enable OpenID authentication for Kyoo.";
+ public string Description => "Enable an authentication/permission system for Kyoo (via Jwt or ApKeys).";
///
public Dictionary Configuration => new()
{
{ AuthenticationOption.Path, typeof(AuthenticationOption) },
{ PermissionOption.Path, typeof(PermissionOption) },
- { CertificateOption.Path, typeof(CertificateOption) }
};
///
@@ -70,11 +63,6 @@ namespace Kyoo.Authentication
///
private readonly IConfiguration _configuration;
- ///
- /// The logger used to allow IdentityServer to log things.
- ///
- private readonly ILogger _logger;
-
///
/// The environment information to check if the app runs in debug mode
///
@@ -84,16 +72,11 @@ namespace Kyoo.Authentication
/// Create a new authentication module instance and use the given configuration and environment.
///
/// The configuration to use
- /// The logger used to allow IdentityServer to log things
/// The environment information to check if the app runs in debug mode
- [SuppressMessage("ReSharper", "ContextualLoggerProblem",
- Justification = "The logger is used for a dependency that is not created via the container.")]
public AuthenticationModule(IConfiguration configuration,
- ILogger logger,
IWebHostEnvironment environment)
{
_configuration = configuration;
- _logger = logger;
_environment = environment;
}
@@ -101,59 +84,29 @@ namespace Kyoo.Authentication
public void Configure(ContainerBuilder builder)
{
builder.RegisterType().As().SingleInstance();
-
- DefaultCorsPolicyService cors = new(_logger)
- {
- AllowedOrigins = { _configuration.GetPublicUrl().GetLeftPart(UriPartial.Authority) }
- };
- builder.RegisterInstance(cors).As().SingleInstance();
}
///
public void Configure(IServiceCollection services)
{
Uri publicUrl = _configuration.GetPublicUrl();
-
- if (_environment.IsDevelopment())
- IdentityModelEventSource.ShowPII = true;
-
- services.AddControllers();
+ AuthenticationOption jwt = new();
+ _configuration.GetSection(AuthenticationOption.Path).Bind(jwt);
// TODO handle direct-videos with bearers (probably add a cookie and a app.Use to translate that for videos)
- // TODO Check if tokens should be stored.
- List clients = new();
- _configuration.GetSection("authentication:clients").Bind(clients);
- CertificateOption certificateOptions = new();
- _configuration.GetSection(CertificateOption.Path).Bind(certificateOptions);
-
- clients.AddRange(IdentityContext.GetClients());
- foreach (Client client in clients)
- {
- client.RedirectUris = client.RedirectUris
- .Select(x => x.StartsWith("/") ? publicUrl.ToString().TrimEnd('/') + x : x)
- .ToArray();
- }
-
- services.AddIdentityServer(options =>
- {
- options.IssuerUri = publicUrl.ToString();
- options.UserInteraction.LoginUrl = $"{publicUrl}login";
- options.UserInteraction.ErrorUrl = $"{publicUrl}error";
- options.UserInteraction.LogoutUrl = $"{publicUrl}logout";
- })
- .AddInMemoryIdentityResources(IdentityContext.GetIdentityResources())
- .AddInMemoryApiScopes(IdentityContext.GetScopes())
- .AddInMemoryApiResources(IdentityContext.GetApis())
- .AddInMemoryClients(clients)
- .AddProfileService()
- .AddSigninKeys(certificateOptions);
-
- services.AddAuthentication()
+ services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
- options.Authority = publicUrl.ToString();
- options.Audience = "kyoo";
- options.RequireHttpsMetadata = false;
+ options.TokenValidationParameters = new TokenValidationParameters
+ {
+ ValidateIssuer = true,
+ ValidateAudience = true,
+ ValidateLifetime = true,
+ ValidateIssuerSigningKey = true,
+ ValidIssuer = publicUrl.ToString(),
+ ValidAudience = publicUrl.ToString(),
+ IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwt.Secret))
+ };
});
}
diff --git a/src/Kyoo.Authentication/Controllers/Certificates.cs b/src/Kyoo.Authentication/Controllers/Certificates.cs
deleted file mode 100644
index 05cb87cd..00000000
--- a/src/Kyoo.Authentication/Controllers/Certificates.cs
+++ /dev/null
@@ -1,137 +0,0 @@
-// Kyoo - A portable and vast media library solution.
-// Copyright (c) Kyoo.
-//
-// See AUTHORS.md and LICENSE file in the project root for full license information.
-//
-// Kyoo is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// any later version.
-//
-// Kyoo is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Kyoo. If not, see .
-
-using System;
-using System.IO;
-using System.Security.Cryptography.X509Certificates;
-using Kyoo.Authentication.Models;
-using Microsoft.Extensions.DependencyInjection;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Generators;
-using Org.BouncyCastle.Crypto.Operators;
-using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Pkcs;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.X509;
-using X509Certificate = Org.BouncyCastle.X509.X509Certificate;
-
-namespace Kyoo.Authentication
-{
- ///
- /// A class containing multiple extensions methods to manage certificates.
- ///
- public static class Certificates
- {
- ///
- /// Add the certificate file to the identity server. If the certificate will expire soon, automatically renew it.
- /// If no certificate exists, one is generated.
- ///
- /// The identity server that will be modified.
- /// The certificate options
- /// The initial builder to allow chain-calls.
- public static IIdentityServerBuilder AddSigninKeys(this IIdentityServerBuilder builder,
- CertificateOption options)
- {
- X509Certificate2 certificate = _GetCertificate(options);
- builder.AddSigningCredential(certificate);
-
- if (certificate.NotAfter.AddDays(-7) <= DateTime.UtcNow)
- {
- Console.WriteLine("Signin certificate will expire soon, renewing it.");
- if (File.Exists(options.OldFile))
- File.Delete(options.OldFile);
- File.Move(options.File, options.OldFile);
- builder.AddValidationKey(_GenerateCertificate(options.File, options.Password));
- }
- else if (File.Exists(options.OldFile))
- builder.AddValidationKey(_GetExistingCredential(options.OldFile, options.Password));
- return builder;
- }
-
- ///
- /// Get or generate the sign-in certificate.
- ///
- /// The certificate options
- /// A valid certificate
- private static X509Certificate2 _GetCertificate(CertificateOption options)
- {
- return File.Exists(options.File)
- ? _GetExistingCredential(options.File, options.Password)
- : _GenerateCertificate(options.File, options.Password);
- }
-
- ///
- /// Load a certificate from a file
- ///
- /// The path of the certificate
- /// The password of the certificate
- /// The loaded certificate
- private static X509Certificate2 _GetExistingCredential(string file, string password)
- {
- X509KeyStorageFlags storeFlags = X509KeyStorageFlags.MachineKeySet |
- X509KeyStorageFlags.PersistKeySet |
- X509KeyStorageFlags.Exportable;
- return new X509Certificate2(file, password, storeFlags);
- }
-
- ///
- /// Generate a new certificate key and put it in the file at .
- ///
- /// The path of the output file
- /// The password of the new certificate
- /// The generated certificate
- private static X509Certificate2 _GenerateCertificate(string file, string password)
- {
- SecureRandom random = new();
-
- X509V3CertificateGenerator certificateGenerator = new();
- certificateGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One,
- BigInteger.ValueOf(long.MaxValue), random));
- certificateGenerator.SetIssuerDN(new X509Name($"C=NL, O=SDG, CN=Kyoo"));
- certificateGenerator.SetSubjectDN(new X509Name($"C=NL, O=SDG, CN=Kyoo"));
- certificateGenerator.SetNotBefore(DateTime.UtcNow.Date);
- certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddMonths(3));
-
- KeyGenerationParameters keyGenerationParameters = new(random, 2048);
- RsaKeyPairGenerator keyPairGenerator = new();
- keyPairGenerator.Init(keyGenerationParameters);
-
- AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
- certificateGenerator.SetPublicKey(subjectKeyPair.Public);
-
- const string signatureAlgorithm = "MD5WithRSA";
- Asn1SignatureFactory signatureFactory = new(signatureAlgorithm, subjectKeyPair.Private);
- X509Certificate bouncyCert = certificateGenerator.Generate(signatureFactory);
-
- Pkcs12Store store = new Pkcs12StoreBuilder().Build();
- store.SetKeyEntry("Kyoo_key", new AsymmetricKeyEntry(subjectKeyPair.Private), new[]
- {
- new X509CertificateEntry(bouncyCert)
- });
-
- using MemoryStream pfxStream = new();
- store.Save(pfxStream, password.ToCharArray(), random);
- X509Certificate2 certificate = new(pfxStream.ToArray(), password, X509KeyStorageFlags.Exportable);
- using FileStream fileStream = File.OpenWrite(file);
- pfxStream.WriteTo(fileStream);
- return certificate;
- }
- }
-}
diff --git a/src/Kyoo.Authentication/Extensions.cs b/src/Kyoo.Authentication/Extensions.cs
index 73b9deed..658da84e 100644
--- a/src/Kyoo.Authentication/Extensions.cs
+++ b/src/Kyoo.Authentication/Extensions.cs
@@ -19,9 +19,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
-using IdentityModel;
-using IdentityServer4;
-using Kyoo.Abstractions.Models;
namespace Kyoo.Authentication
{
@@ -30,35 +27,6 @@ namespace Kyoo.Authentication
///
public static class Extensions
{
- ///
- /// Get claims of an user.
- ///
- /// The user concerned
- /// The list of claims the user has
- public static ICollection GetClaims(this User user)
- {
- return new[]
- {
- new Claim(JwtClaimTypes.Subject, user.ID.ToString()),
- new Claim(JwtClaimTypes.Name, user.Username),
- new Claim(JwtClaimTypes.Picture, $"api/account/picture/{user.Slug}")
- };
- }
-
- ///
- /// Convert a user to an IdentityServerUser.
- ///
- /// The user to convert.
- /// The corresponding identity server user.
- public static IdentityServerUser ToIdentityUser(this User user)
- {
- return new IdentityServerUser(user.ID.ToString())
- {
- DisplayName = user.Username,
- AdditionalClaims = new[] { new Claim("permissions", string.Join(',', user.Permissions)) }
- };
- }
-
///
/// Get the permissions of an user.
///
diff --git a/src/Kyoo.Authentication/Kyoo.Authentication.csproj b/src/Kyoo.Authentication/Kyoo.Authentication.csproj
index 2940dc1f..fd863584 100644
--- a/src/Kyoo.Authentication/Kyoo.Authentication.csproj
+++ b/src/Kyoo.Authentication/Kyoo.Authentication.csproj
@@ -1,19 +1,16 @@
-
+
../Kyoo.WebLogin/
-
-
-
-
-
+
+
-
+
diff --git a/src/Kyoo.Authentication/Models/IdentityContext.cs b/src/Kyoo.Authentication/Models/IdentityContext.cs
deleted file mode 100644
index 4c946653..00000000
--- a/src/Kyoo.Authentication/Models/IdentityContext.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-// Kyoo - A portable and vast media library solution.
-// Copyright (c) Kyoo.
-//
-// See AUTHORS.md and LICENSE file in the project root for full license information.
-//
-// Kyoo is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// any later version.
-//
-// Kyoo is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Kyoo. If not, see .
-
-using System.Collections.Generic;
-using System.Linq;
-using IdentityServer4.Models;
-
-namespace Kyoo.Authentication
-{
- ///
- /// The hard coded context of the identity server.
- ///
- public static class IdentityContext
- {
- ///
- /// The list of identity resources supported (email, profile and openid)
- ///
- /// The list of identity resources supported
- public static IEnumerable GetIdentityResources()
- {
- return new List
- {
- new IdentityResources.OpenId(),
- new IdentityResources.Email(),
- new IdentityResources.Profile()
- };
- }
-
- ///
- /// Get the list of officially supported clients.
- ///
- ///
- /// You can add custom clients in the settings.json file.
- ///
- /// The list of officially supported clients.
- public static IEnumerable GetClients()
- {
- return new List
- {
- new()
- {
- ClientId = "kyoo.webapp",
-
- AccessTokenType = AccessTokenType.Jwt,
- AllowedGrantTypes = GrantTypes.Code,
- RequirePkce = true,
- RequireClientSecret = false,
-
- AllowAccessTokensViaBrowser = true,
- AllowOfflineAccess = true,
- RequireConsent = false,
-
- AllowedScopes = { "openid", "profile", "kyoo.read", "kyoo.write", "kyoo.play", "kyoo.admin" },
- RedirectUris = { "/", "/silent.html" },
- PostLogoutRedirectUris = { "/logout" }
- }
- };
- }
-
- ///
- /// The list of scopes supported by the API.
- ///
- /// The list of scopes
- public static IEnumerable GetScopes()
- {
- return new[]
- {
- new ApiScope
- {
- Name = "kyoo.read",
- DisplayName = "Read only access to the API.",
- },
- new ApiScope
- {
- Name = "kyoo.write",
- DisplayName = "Read and write access to the public API"
- },
- new ApiScope
- {
- Name = "kyoo.play",
- DisplayName = "Allow playback of movies and episodes."
- },
- new ApiScope
- {
- Name = "kyoo.admin",
- DisplayName = "Full access to the admin's API and the public API."
- }
- };
- }
-
- ///
- /// The list of APIs (this is used to create Audiences)
- ///
- /// The list of apis
- public static IEnumerable GetApis()
- {
- return new[]
- {
- new ApiResource("kyoo", "Kyoo")
- {
- Scopes = GetScopes().Select(x => x.Name).ToArray()
- }
- };
- }
- }
-}
diff --git a/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs b/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs
index 1b43281f..dc8209aa 100644
--- a/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs
+++ b/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs
@@ -29,9 +29,9 @@ namespace Kyoo.Authentication.Models
public const string Path = "authentication";
///
- /// The options for certificates
+ /// The secret used to encrypt the jwt.
///
- public CertificateOption Certificate { get; set; }
+ public string Secret { get; set; }
///
/// Options for permissions
diff --git a/src/Kyoo.Authentication/Models/Options/CertificateOption.cs b/src/Kyoo.Authentication/Models/Options/CertificateOption.cs
deleted file mode 100644
index 8e697a7f..00000000
--- a/src/Kyoo.Authentication/Models/Options/CertificateOption.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Kyoo - A portable and vast media library solution.
-// Copyright (c) Kyoo.
-//
-// See AUTHORS.md and LICENSE file in the project root for full license information.
-//
-// Kyoo is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// any later version.
-//
-// Kyoo is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Kyoo. If not, see .
-
-namespace Kyoo.Authentication.Models
-{
- ///
- /// A typed option model for the certificate
- ///
- public class CertificateOption
- {
- ///
- /// The path to get this option from the root configuration.
- ///
- public const string Path = "authentication:certificate";
-
- ///
- /// The path of the certificate file.
- ///
- public string File { get; set; }
-
- ///
- /// The path of the old certificate file.
- ///
- public string OldFile { get; set; }
-
- ///
- /// The password of the certificates.
- ///
- public string Password { get; set; }
- }
-}
diff --git a/src/Kyoo.Host.Generic/settings.json b/src/Kyoo.Host.Generic/settings.json
index bf5e6a4e..817536c2 100644
--- a/src/Kyoo.Host.Generic/settings.json
+++ b/src/Kyoo.Host.Generic/settings.json
@@ -60,17 +60,11 @@
},
"authentication": {
- "certificate": {
- "file": "certificate.pfx",
- "oldFile": "oldCertificate.pfx",
- "password": "passphrase"
- },
"permissions": {
"default": ["overall.read", "overall.write", "overall.create", "overall.delete", "admin.read", "admin.write"],
"newUser": ["overall.read", "overall.write", "overall.create", "overall.delete", "admin.read", "admin.write"]
},
"profilePicturePath": "users/",
- "clients": []
},
"tvdb": {