Cleaning up the Authentication plugin

This commit is contained in:
Zoe Roux 2021-05-09 16:23:21 +02:00
parent 440e5f4f14
commit 765bd061b7
5 changed files with 29 additions and 178 deletions

View File

@ -10,7 +10,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@ -89,28 +88,10 @@ namespace Kyoo.Authentication
// TODO handle direct-videos with bearers (probably add a ?token query param and a app.Use to translate that for videos)
// TODO Support sign-out, check if login work, check if tokens should be stored.
// TODO Check if tokens should be stored.
// TODO remove unused/commented code, add documentation.
// services.AddIdentityCore<User>()
// .AddSignInManager()
// .AddDefaultTokenProviders()
// .AddUserStore<UserStore>();
// services.AddDbContext<IdentityDatabase>(options =>
// {
// options.UseNpgsql(_configuration.GetDatabaseConnection("postgres"));
// });
// services.AddIdentityCore<User>(o =>
// {
// o.Stores.MaxLengthForKeys = 128;
// })
// .AddSignInManager()
// .AddDefaultTokenProviders()
// .AddEntityFrameworkStores<IdentityDatabase>();
services.Configure<PermissionOption>(_configuration.GetSection(PermissionOption.Path));
services.Configure<CertificateOption>(_configuration.GetSection(CertificateOption.Path));
services.Configure<AuthenticationOption>(_configuration.GetSection(AuthenticationOption.Path));
@ -124,35 +105,15 @@ namespace Kyoo.Authentication
options.UserInteraction.ErrorUrl = $"{publicUrl}/error";
options.UserInteraction.LogoutUrl = $"{publicUrl}/logout";
})
// .AddAspNetIdentity<User>()
// .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())
.AddInMemoryClients(_configuration.GetSection("authentication:clients"))
.AddProfileService<AccountApi>()
.AddSigninKeys(certificateOptions);
// TODO implement means to add clients or api scopes for other plugins.
// TODO split scopes (kyoo.read should be task.read, video.read etc)
// services.AddAuthentication(o =>
// {
// o.DefaultScheme = IdentityConstants.ApplicationScheme;
// o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
// })
// .AddIdentityCookies(_ => { });
services.AddAuthentication()
.AddJwtBearer(options =>
{
@ -171,10 +132,10 @@ namespace Kyoo.Authentication
{
options.AddPolicy(permission, policy =>
{
// policy.AuthenticationSchemes.Add(IdentityConstants.ApplicationScheme);
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.AddRequirements(new AuthRequirement(permission));
// policy.RequireScope($"kyoo.{permission.ToLower()}");
// Scopes are disables to support default permissions.
// To enable them, use the following line: policy.RequireScope($"kyoo.{permission.ToLower()}");
});
}
});

View File

@ -1,133 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Kyoo.Controllers;
using Kyoo.Models;
using Microsoft.AspNetCore.Identity;
namespace Kyoo.Authentication
{
/// <summary>
/// An implementation of an <see cref="IUserStore{TUser}"/> that uses an <see cref="IUserRepository"/>.
/// </summary>
public class UserStore : IUserStore<User>
{
/// <summary>
/// The user repository used to store users.
/// </summary>
private readonly IUserRepository _users;
/// <summary>
/// Create a new <see cref="UserStore"/>.
/// </summary>
/// <param name="users">The user repository to use</param>
public UserStore(IUserRepository users)
{
_users = users;
}
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Implementation of the IDisposable pattern
/// </summary>
/// <param name="disposing">True if this class should be disposed.</param>
protected virtual void Dispose(bool disposing)
{
bool _ = disposing;
// Not implemented because this class has nothing to dispose.
}
/// <inheritdoc />
public Task<string> GetUserIdAsync(User user, CancellationToken cancellationToken)
{
return Task.FromResult(user.ID.ToString());
}
/// <inheritdoc />
public Task<string> GetUserNameAsync(User user, CancellationToken cancellationToken)
{
return Task.FromResult(user.Username);
}
/// <inheritdoc />
public Task SetUserNameAsync(User user, string userName, CancellationToken cancellationToken)
{
user.Username = userName;
return Task.CompletedTask;
}
/// <inheritdoc />
public Task<string> GetNormalizedUserNameAsync(User user, CancellationToken cancellationToken)
{
return Task.FromResult(user.Slug);
}
/// <inheritdoc />
public Task SetNormalizedUserNameAsync(User user, string normalizedName, CancellationToken cancellationToken)
{
user.Slug = normalizedName;
return Task.CompletedTask;
}
/// <inheritdoc />
public async Task<IdentityResult> CreateAsync(User user, CancellationToken cancellationToken)
{
try
{
await _users.Create(user);
return IdentityResult.Success;
}
catch (Exception ex)
{
return IdentityResult.Failed(new IdentityError {Code = ex.GetType().Name, Description = ex.Message});
}
}
/// <inheritdoc />
public async Task<IdentityResult> UpdateAsync(User user, CancellationToken cancellationToken)
{
try
{
await _users.Edit(user, false);
return IdentityResult.Success;
}
catch (Exception ex)
{
return IdentityResult.Failed(new IdentityError {Code = ex.GetType().Name, Description = ex.Message});
}
}
/// <inheritdoc />
public async Task<IdentityResult> DeleteAsync(User user, CancellationToken cancellationToken)
{
try
{
await _users.Delete(user);
return IdentityResult.Success;
}
catch (Exception ex)
{
return IdentityResult.Failed(new IdentityError {Code = ex.GetType().Name, Description = ex.Message});
}
}
/// <inheritdoc />
public Task<User> FindByIdAsync(string userId, CancellationToken cancellationToken)
{
return _users.GetOrDefault(int.Parse(userId));
}
/// <inheritdoc />
public Task<User> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
return _users.GetOrDefault(normalizedUserName);
}
}
}

View File

@ -4,8 +4,15 @@ using IdentityServer4.Models;
namespace Kyoo.Authentication
{
/// <summary>
/// The hard coded context of the identity server.
/// </summary>
public static class IdentityContext
{
/// <summary>
/// The list of identity resources supported (email, profile and openid)
/// </summary>
/// <returns>The list of identity resources supported</returns>
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
@ -16,6 +23,13 @@ namespace Kyoo.Authentication
};
}
/// <summary>
/// The list of officially supported clients.
/// </summary>
/// <remarks>
/// You can add custom clients in the settings.json file.
/// </remarks>
/// <returns>The list of officially supported clients.</returns>
public static IEnumerable<Client> GetClients()
{
return new List<Client>
@ -40,6 +54,10 @@ namespace Kyoo.Authentication
};
}
/// <summary>
/// The list of scopes supported by the API.
/// </summary>
/// <returns>The list of scopes</returns>
public static IEnumerable<ApiScope> GetScopes()
{
return new[]
@ -67,6 +85,10 @@ namespace Kyoo.Authentication
};
}
/// <summary>
/// The list of APIs (this is used to create Audiences)
/// </summary>
/// <returns>The list of apis</returns>
public static IEnumerable<ApiResource> GetApis()
{
return new[]

View File

@ -35,7 +35,8 @@
"default": [],
"newUser": ["read", "play", "write", "admin"]
},
"profilePicturePath": "users/"
"profilePicturePath": "users/",
"clients": []
},