Fix ApiKey configuration options

This commit is contained in:
Zoe Roux 2023-03-20 16:07:28 +09:00
parent 9e98bf3532
commit 02214a127c
5 changed files with 25 additions and 32 deletions

View File

@ -62,15 +62,17 @@ namespace Kyoo.Authentication
public void Configure(IServiceCollection services) public void Configure(IServiceCollection services)
{ {
string secret = _configuration.GetValue("AUTHENTICATION_SECRET", AuthenticationOption.DefaultSecret); string secret = _configuration.GetValue("AUTHENTICATION_SECRET", AuthenticationOption.DefaultSecret);
services.Configure<AuthenticationOption>(x => PermissionOption permissions = new()
{ {
x.Secret = secret; Default = _configuration.GetValue<string>("UNLOGGED_PERMISSIONS", "overall.read").Split(','),
x.Permissions = new PermissionOption NewUser = _configuration.GetValue<string>("DEFAULT_PERMISSIONS", "overall.read").Split(','),
{ ApiKeys = _configuration.GetValue("KYOO_APIKEYS", string.Empty).Split(','),
Default = _configuration.GetValue<string>("UNLOGGED_PERMISSIONS", "overall.read").Split(','), };
NewUser = _configuration.GetValue<string>("DEFAULT_PERMISSIONS", "overall.read").Split(','), services.AddSingleton<PermissionOption>(permissions);
ApiKeys = _configuration.GetValue("KYOO_APIKEYS", string.Empty).Split(','), services.AddSingleton<AuthenticationOption>(new AuthenticationOption()
}; {
Secret = secret,
Permissions = permissions,
}); });
// TODO handle direct-videos with bearers (probably add a cookie and a app.Use to translate that for videos) // TODO handle direct-videos with bearers (probably add a cookie and a app.Use to translate that for videos)

View File

@ -30,7 +30,6 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
namespace Kyoo.Authentication namespace Kyoo.Authentication
@ -44,13 +43,13 @@ namespace Kyoo.Authentication
/// <summary> /// <summary>
/// The permissions options to retrieve default permissions. /// The permissions options to retrieve default permissions.
/// </summary> /// </summary>
private readonly IOptionsMonitor<PermissionOption> _options; private readonly PermissionOption _options;
/// <summary> /// <summary>
/// Create a new factory with the given options. /// Create a new factory with the given options.
/// </summary> /// </summary>
/// <param name="options">The option containing default values.</param> /// <param name="options">The option containing default values.</param>
public PermissionValidator(IOptionsMonitor<PermissionOption> options) public PermissionValidator(PermissionOption options)
{ {
_options = options; _options = options;
} }
@ -90,7 +89,7 @@ namespace Kyoo.Authentication
/// <summary> /// <summary>
/// The permissions options to retrieve default permissions. /// The permissions options to retrieve default permissions.
/// </summary> /// </summary>
private readonly IOptionsMonitor<PermissionOption> _options; private readonly PermissionOption _options;
/// <summary> /// <summary>
/// Create a new permission validator with the given options. /// Create a new permission validator with the given options.
@ -103,7 +102,7 @@ namespace Kyoo.Authentication
string permission, string permission,
Kind kind, Kind kind,
Group group, Group group,
IOptionsMonitor<PermissionOption> options) PermissionOption options)
{ {
_permission = permission; _permission = permission;
_kind = kind; _kind = kind;
@ -117,7 +116,7 @@ namespace Kyoo.Authentication
/// <param name="partialInfo">The partial permission to validate.</param> /// <param name="partialInfo">The partial permission to validate.</param>
/// <param name="group">The group of the permission.</param> /// <param name="group">The group of the permission.</param>
/// <param name="options">The option containing default values.</param> /// <param name="options">The option containing default values.</param>
public PermissionValidatorFilter(object partialInfo, Group? group, IOptionsMonitor<PermissionOption> options) public PermissionValidatorFilter(object partialInfo, Group? group, PermissionOption options)
{ {
switch (partialInfo) switch (partialInfo)
{ {
@ -183,7 +182,7 @@ namespace Kyoo.Authentication
} }
else if (res.None) else if (res.None)
{ {
ICollection<string> permissions = _options.CurrentValue.Default ?? Array.Empty<string>(); ICollection<string> permissions = _options.Default ?? Array.Empty<string>();
if (permissions.All(x => x != permStr && x != overallStr)) if (permissions.All(x => x != permStr && x != overallStr))
{ {
context.Result = _ErrorResult($"Unlogged user does not have permission {permStr} or {overallStr}", StatusCodes.Status401Unauthorized); context.Result = _ErrorResult($"Unlogged user does not have permission {permStr} or {overallStr}", StatusCodes.Status401Unauthorized);
@ -199,7 +198,7 @@ namespace Kyoo.Authentication
{ {
if (!context.HttpContext.Request.Headers.TryGetValue("X-API-Key", out StringValues apiKey)) if (!context.HttpContext.Request.Headers.TryGetValue("X-API-Key", out StringValues apiKey))
return AuthenticateResult.NoResult(); return AuthenticateResult.NoResult();
if (!_options.CurrentValue.ApiKeys.Contains<string>(apiKey)) if (!_options.ApiKeys.Contains<string>(apiKey))
return AuthenticateResult.Fail("Invalid API-Key."); return AuthenticateResult.Fail("Invalid API-Key.");
return AuthenticateResult.Success( return AuthenticateResult.Success(
new AuthenticationTicket( new AuthenticationTicket(

View File

@ -26,7 +26,6 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Authentication.Models; using Kyoo.Authentication.Models;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
namespace Kyoo.Authentication namespace Kyoo.Authentication
@ -39,13 +38,13 @@ namespace Kyoo.Authentication
/// <summary> /// <summary>
/// The options that this controller will use. /// The options that this controller will use.
/// </summary> /// </summary>
private readonly IOptions<AuthenticationOption> _options; private readonly AuthenticationOption _options;
/// <summary> /// <summary>
/// Create a new <see cref="TokenController"/>. /// Create a new <see cref="TokenController"/>.
/// </summary> /// </summary>
/// <param name="options">The options that this controller will use.</param> /// <param name="options">The options that this controller will use.</param>
public TokenController(IOptions<AuthenticationOption> options) public TokenController(AuthenticationOption options)
{ {
_options = options; _options = options;
} }
@ -55,7 +54,7 @@ namespace Kyoo.Authentication
{ {
expireIn = new TimeSpan(1, 0, 0); expireIn = new TimeSpan(1, 0, 0);
SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Secret));
SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature); SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature);
string permissions = user.Permissions != null string permissions = user.Permissions != null
? string.Join(',', user.Permissions) ? string.Join(',', user.Permissions)
@ -80,7 +79,7 @@ namespace Kyoo.Authentication
/// <inheritdoc /> /// <inheritdoc />
public Task<string> CreateRefreshToken(User user) public Task<string> CreateRefreshToken(User user)
{ {
SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Secret));
SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature); SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature);
JwtSecurityToken token = new( JwtSecurityToken token = new(
signingCredentials: credential, signingCredentials: credential,
@ -99,7 +98,7 @@ namespace Kyoo.Authentication
/// <inheritdoc /> /// <inheritdoc />
public int GetRefreshTokenUserID(string refreshToken) public int GetRefreshTokenUserID(string refreshToken)
{ {
SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Secret));
JwtSecurityTokenHandler tokenHandler = new(); JwtSecurityTokenHandler tokenHandler = new();
ClaimsPrincipal principal; ClaimsPrincipal principal;
try try

View File

@ -29,7 +29,6 @@ using Kyoo.Authentication.Models;
using Kyoo.Authentication.Models.DTO; using Kyoo.Authentication.Models.DTO;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using static Kyoo.Abstractions.Models.Utils.Constants; using static Kyoo.Abstractions.Models.Utils.Constants;
using BCryptNet = BCrypt.Net.BCrypt; using BCryptNet = BCrypt.Net.BCrypt;
@ -57,7 +56,7 @@ namespace Kyoo.Authentication.Views
/// <summary> /// <summary>
/// The permisson options. /// The permisson options.
/// </summary> /// </summary>
private readonly IOptionsMonitor<PermissionOption> _permissions; private readonly PermissionOption _permissions;
/// <summary> /// <summary>
/// Create a new <see cref="AuthApi"/>. /// Create a new <see cref="AuthApi"/>.
@ -65,7 +64,7 @@ namespace Kyoo.Authentication.Views
/// <param name="users">The repository used to check if the user exists.</param> /// <param name="users">The repository used to check if the user exists.</param>
/// <param name="token">The token generator.</param> /// <param name="token">The token generator.</param>
/// <param name="permissions">The permission opitons.</param> /// <param name="permissions">The permission opitons.</param>
public AuthApi(IUserRepository users, ITokenController token, IOptionsMonitor<PermissionOption> permissions) public AuthApi(IUserRepository users, ITokenController token, PermissionOption permissions)
{ {
_users = users; _users = users;
_token = token; _token = token;
@ -124,7 +123,7 @@ namespace Kyoo.Authentication.Views
public async Task<ActionResult<JwtToken>> Register([FromBody] RegisterRequest request) public async Task<ActionResult<JwtToken>> Register([FromBody] RegisterRequest request)
{ {
User user = request.ToUser(); User user = request.ToUser();
user.Permissions = _permissions.CurrentValue.NewUser; user.Permissions = _permissions.NewUser;
// If no users exists, the new one will be an admin. Give it every permissions. // If no users exists, the new one will be an admin. Give it every permissions.
if (await _users.GetOrDefault(where: x => true) == null) if (await _users.GetOrDefault(where: x => true) == null)
user.Permissions = PermissionOption.Admin; user.Permissions = PermissionOption.Admin;

View File

@ -66,12 +66,6 @@ namespace Kyoo.Host
builder.RegisterComposite<FileSystemComposite, IFileSystem>().InstancePerLifetimeScope(); builder.RegisterComposite<FileSystemComposite, IFileSystem>().InstancePerLifetimeScope();
} }
/// <inheritdoc />
public void Configure(IServiceCollection services)
{
services.Configure<BasicOptions>(_configuration.GetSection(BasicOptions.Path));
}
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<IStartupAction> ConfigureSteps => new[] public IEnumerable<IStartupAction> ConfigureSteps => new[]
{ {