Auto generate jwt secret (#432)

This commit is contained in:
Zoe Roux 2024-04-23 18:35:25 +02:00 committed by GitHub
commit 58f0f3d74b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1515 additions and 57 deletions

View File

@ -32,9 +32,8 @@ COMPOSE_PROFILES=cpu # cpu (no hardware acceleration) or vaapi or qsv or nvidia
GOCODER_PRESET=fast
# The following two values should be set to a random sequence of characters.
# You MUST change thoses when installing kyoo (for security)
AUTHENTICATION_SECRET="4c@mraGB!KRfF@kpS8739y9FcHemKxBsqqxLbdR?"
# The following value should be set to a random sequence of characters.
# You MUST change it when installing kyoo (for security)
# You can input multiple api keys separated by a ,
KYOO_APIKEYS=t7H5!@4iMNsAaSJQ49pat4jprJgTcF656if#J3

View File

@ -1,2 +1,4 @@
--project
src/Kyoo.Postgresql
--msbuildprojectextensionspath
out/obj/Kyoo.Postgresql

View File

@ -18,7 +18,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers;
using Kyoo.Authentication.Models;
@ -36,10 +35,6 @@ public static class AuthenticationModule
{
public static void ConfigureAuthentication(this WebApplicationBuilder builder)
{
string secret = builder.Configuration.GetValue(
"AUTHENTICATION_SECRET",
AuthenticationOption.DefaultSecret
)!;
PermissionOption options =
new()
{
@ -114,9 +109,9 @@ public static class AuthenticationModule
),
};
builder.Services.AddSingleton(options);
builder.Services.AddSingleton(
new AuthenticationOption() { Secret = secret, Permissions = options, }
);
byte[] secret = builder.Configuration.GetValue<byte[]>("AUTHENTICATION_SECRET")!;
builder.Services.AddSingleton(new AuthenticationOption() { Secret = secret });
builder
.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
@ -145,7 +140,7 @@ public static class AuthenticationModule
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret))
IssuerSigningKey = new SymmetricSecurityKey(secret)
};
});

View File

@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Kyoo.Abstractions.Models;
using Kyoo.Authentication.Models;
@ -29,31 +28,14 @@ using Microsoft.IdentityModel.Tokens;
namespace Kyoo.Authentication;
/// <summary>
/// The service that controls jwt creation and validation.
/// </summary>
public class TokenController : ITokenController
public class TokenController(AuthenticationOption options) : ITokenController
{
/// <summary>
/// The options that this controller will use.
/// </summary>
private readonly AuthenticationOption _options;
/// <summary>
/// Create a new <see cref="TokenController"/>.
/// </summary>
/// <param name="options">The options that this controller will use.</param>
public TokenController(AuthenticationOption options)
{
_options = options;
}
/// <inheritdoc />
public string CreateAccessToken(User user, out TimeSpan expireIn)
{
expireIn = new TimeSpan(1, 0, 0);
SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Secret));
SymmetricSecurityKey key = new(options.Secret);
SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature);
string permissions =
user.Permissions != null ? string.Join(',', user.Permissions) : string.Empty;
@ -79,7 +61,7 @@ public class TokenController : ITokenController
/// <inheritdoc />
public Task<string> CreateRefreshToken(User user)
{
SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Secret));
SymmetricSecurityKey key = new(options.Secret);
SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature);
JwtSecurityToken token =
new(
@ -99,7 +81,7 @@ public class TokenController : ITokenController
/// <inheritdoc />
public Guid GetRefreshTokenUserID(string refreshToken)
{
SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Secret));
SymmetricSecurityKey key = new(options.Secret);
JwtSecurityTokenHandler tokenHandler = new();
ClaimsPrincipal principal;
try

View File

@ -18,28 +18,7 @@
namespace Kyoo.Authentication.Models;
/// <summary>
/// The main authentication options.
/// </summary>
public class AuthenticationOption
{
/// <summary>
/// The path to get this option from the root configuration.
/// </summary>
public const string Path = "authentication";
/// <summary>
/// The default jwt secret.
/// </summary>
public const string DefaultSecret = "4c@mraGB!KRfF@kpS8739y9FcHemKxBsqqxLbdR?";
/// <summary>
/// The secret used to encrypt the jwt.
/// </summary>
public string Secret { get; set; } = DefaultSecret;
/// <summary>
/// Options for permissions
/// </summary>
public PermissionOption Permissions { get; set; } = new();
public byte[] Secret { get; set; }
}

View File

@ -17,9 +17,11 @@
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Linq;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Core.Controllers;
using Kyoo.Postgresql;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

View File

@ -72,9 +72,11 @@ builder.Host.UseSerilog();
builder.Services.ConfigureMvc();
builder.Services.ConfigureOpenApi();
// configure postgres first to allow other services to depend on db config
builder.ConfigurePostgres();
builder.ConfigureKyoo();
builder.ConfigureAuthentication();
builder.ConfigurePostgres();
builder.ConfigureMeilisearch();
builder.ConfigureRabbitMq();

View File

@ -67,6 +67,8 @@ public abstract class DatabaseContext : DbContext
public DbSet<Issue> Issues { get; set; }
public DbSet<ServerOption> Options { get; set; }
/// <summary>
/// Add a many to many link between two resources.
/// </summary>
@ -353,6 +355,8 @@ public abstract class DatabaseContext : DbContext
_HasJson<User, string>(modelBuilder, x => x.Settings);
_HasJson<User, ExternalToken>(modelBuilder, x => x.ExternalId);
_HasJson<Issue, object>(modelBuilder, x => x.Extra);
modelBuilder.Entity<ServerOption>().HasKey(x => x.Key);
}
public override int SaveChanges()

View File

@ -0,0 +1,28 @@
using System;
using System.Linq;
using Kyoo.Postgresql;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
public class DbConfigurationProvider(Action<DbContextOptionsBuilder> action) : ConfigurationProvider
{
public override void Load()
{
DbContextOptionsBuilder<PostgresContext> builder = new();
action(builder);
using var context = new PostgresContext(builder.Options, null!);
Data = context.Options.ToDictionary(c => c.Key, c => c.Value)!;
}
}
public class DbConfigurationSource(Action<DbContextOptionsBuilder> action) : IConfigurationSource
{
public IConfigurationProvider Build(IConfigurationBuilder builder) =>
new DbConfigurationProvider(action);
}
public class ServerOption
{
public string Key { get; set; }
public string Value { get; set; }
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
using System;
using System.Security.Cryptography;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Kyoo.Postgresql.Migrations
{
/// <inheritdoc />
public partial class AddServerOptions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "options",
columns: table => new
{
key = table.Column<string>(type: "text", nullable: false),
value = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_options", x => x.key);
}
);
byte[] secret = new byte[128];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(secret);
migrationBuilder.InsertData(
"options",
new[] { "key", "value" },
new[] { "AUTHENTICATION_SECRET", Convert.ToBase64String(secret) }
);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(name: "options");
}
}
}

View File

@ -688,6 +688,23 @@ namespace Kyoo.Postgresql.Migrations
b.ToTable("users", (string)null);
});
modelBuilder.Entity("ServerOption", b =>
{
b.Property<string>("Key")
.HasColumnType("text")
.HasColumnName("key");
b.Property<string>("Value")
.IsRequired()
.HasColumnType("text")
.HasColumnName("value");
b.HasKey("Key")
.HasName("pk_options");
b.ToTable("options", (string)null);
});
modelBuilder.Entity("link_collection_movie", b =>
{
b.Property<Guid>("collection_id")

View File

@ -16,6 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Data.Common;
using Kyoo.Abstractions.Models;
using Microsoft.AspNetCore.Builder;
@ -69,5 +70,14 @@ public static class PostgresModule
);
builder.Services.AddHealthChecks().AddDbContextCheck<DatabaseContext>();
builder.Configuration.AddDbConfigurationProvider(x => x.UseNpgsql(dataSource));
}
private static void AddDbConfigurationProvider(
this IConfigurationBuilder builder,
Action<DbContextOptionsBuilder> action
)
{
builder.Add(new DbConfigurationSource(action));
}
}