mirror of
https://github.com/hmaxnl/DotBased.git
synced 2025-01-18 18:14:20 +01:00
Compare commits
2 Commits
c7d654a0ba
...
c092b8a679
Author | SHA1 | Date | |
---|---|---|---|
|
c092b8a679 | ||
|
2b17ed4cd7 |
|
@ -1,6 +0,0 @@
|
||||||
namespace DotBased.ASP.Auth;
|
|
||||||
|
|
||||||
public class AuthService
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
36
DotBased.ASP.Auth/BasedAuthBuilder.cs
Normal file
36
DotBased.ASP.Auth/BasedAuthBuilder.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using DotBased.ASP.Auth.Scheme;
|
||||||
|
using DotBased.ASP.Auth.Services;
|
||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace DotBased.ASP.Auth;
|
||||||
|
|
||||||
|
public class BasedAuthBuilder
|
||||||
|
{
|
||||||
|
public BasedAuthBuilder(IServiceCollection services, Action<BasedAuthConfiguration>? configurationAction = null)
|
||||||
|
{
|
||||||
|
_services = services;
|
||||||
|
Configuration = new BasedAuthConfiguration();
|
||||||
|
configurationAction?.Invoke(Configuration);
|
||||||
|
|
||||||
|
services.AddSingleton<BasedAuthConfiguration>(Configuration);
|
||||||
|
if (Configuration.AuthDataProviderType == null)
|
||||||
|
throw new ArgumentNullException(nameof(Configuration.AuthDataProviderType), $"No '{nameof(IAuthDataProvider)}' configured!");
|
||||||
|
services.AddScoped(typeof(IAuthDataProvider), Configuration.AuthDataProviderType);
|
||||||
|
if (Configuration.SessionStateProviderType == null)
|
||||||
|
throw new ArgumentNullException(nameof(Configuration.SessionStateProviderType), $"No '{nameof(ISessionStateProvider)}' configured!");
|
||||||
|
services.AddScoped(typeof(ISessionStateProvider), Configuration.SessionStateProviderType);
|
||||||
|
|
||||||
|
services.AddScoped<AuthService>();
|
||||||
|
|
||||||
|
services.AddScoped<AuthenticationStateProvider, BasedServerAuthenticationStateProvider>();
|
||||||
|
services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultScheme = BasedAuthenticationHandler.AuthenticationScheme;
|
||||||
|
}).AddScheme<BasedAuthenticationHandlerOptions, BasedAuthenticationHandler>(BasedAuthenticationHandler.AuthenticationScheme, null);
|
||||||
|
services.AddAuthorization();
|
||||||
|
services.AddCascadingAuthenticationState();
|
||||||
|
}
|
||||||
|
public BasedAuthConfiguration Configuration { get; }
|
||||||
|
private readonly IServiceCollection _services;
|
||||||
|
}
|
|
@ -7,12 +7,36 @@ public class BasedAuthConfiguration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowRegistration { get; set; }
|
public bool AllowRegistration { get; set; }
|
||||||
//TODO: Callback when a user registers, so the application can handle sending emails or generate a code to complete the registration.
|
//TODO: Callback when a user registers, so the application can handle sending emails or generate a code to complete the registration.
|
||||||
|
//TODO: Callback for validation email, phone number
|
||||||
|
/// <summary>
|
||||||
|
/// Allow no passwords on users, not recommended!
|
||||||
|
/// </summary>
|
||||||
|
public bool AllowEmptyPassword { get; set; } = false;
|
||||||
|
/// <summary>
|
||||||
|
/// This path is used for redirecting to the login page.
|
||||||
|
/// </summary>
|
||||||
public string LoginPath { get; set; } = string.Empty;
|
public string LoginPath { get; set; } = string.Empty;
|
||||||
|
/// <summary>
|
||||||
|
/// The path that will be used if the logout is requested.
|
||||||
|
/// </summary>
|
||||||
public string LogoutPath { get; set; } = string.Empty;
|
public string LogoutPath { get; set; } = string.Empty;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The max age before a AuthenticationState will expire (default: 7 days).
|
/// The max age before a AuthenticationState will expire (default: 7 days).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan AuthenticationStateMaxAgeBeforeExpire { get; set; } = TimeSpan.FromDays(7);
|
public TimeSpan AuthenticationStateMaxAgeBeforeExpire { get; set; } = TimeSpan.FromDays(7);
|
||||||
//TODO: Data seeding
|
/// <summary>
|
||||||
public Action<AuthService>? SeedData { get; set; }
|
/// Can be used to seed a default user and/or group for first time use.
|
||||||
|
/// </summary>
|
||||||
|
public Action<IAuthDataProvider>? SeedData { get; set; }
|
||||||
|
|
||||||
|
public Type? AuthDataProviderType { get; private set; }
|
||||||
|
|
||||||
|
public void SetDataProviderType<TDataProviderType>() where TDataProviderType : IAuthDataProvider =>
|
||||||
|
AuthDataProviderType = typeof(TDataProviderType);
|
||||||
|
|
||||||
|
public Type? SessionStateProviderType { get; private set; }
|
||||||
|
|
||||||
|
public void SetSessionStateProviderType<TSessionStateProviderType>()
|
||||||
|
where TSessionStateProviderType : ISessionStateProvider =>
|
||||||
|
SessionStateProviderType = typeof(TSessionStateProviderType);
|
||||||
}
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
using System.Security.Claims;
|
|
||||||
using DotBased.Logging;
|
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
|
||||||
|
|
||||||
namespace DotBased.ASP.Auth;
|
|
||||||
|
|
||||||
// RevalidatingServerAuthenticationStateProvider
|
|
||||||
public class BasedAuthenticationStateProvider : AuthenticationStateProvider
|
|
||||||
{
|
|
||||||
public BasedAuthenticationStateProvider(BasedAuthConfiguration configuration)
|
|
||||||
{
|
|
||||||
_config = configuration;
|
|
||||||
_logger = LogService.RegisterLogger(typeof(BasedAuthenticationStateProvider));
|
|
||||||
}
|
|
||||||
|
|
||||||
private BasedAuthConfiguration _config;
|
|
||||||
private ILogger _logger;
|
|
||||||
private AuthenticationState _anonState = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>() {new Claim(ClaimTypes.Role, "test")})));
|
|
||||||
|
|
||||||
public override Task<AuthenticationState> GetAuthenticationStateAsync()
|
|
||||||
{
|
|
||||||
return Task.FromResult(_anonState);
|
|
||||||
}
|
|
||||||
}
|
|
29
DotBased.ASP.Auth/BasedServerAuthenticationStateProvider.cs
Normal file
29
DotBased.ASP.Auth/BasedServerAuthenticationStateProvider.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Security.Claims;
|
||||||
|
using DotBased.Logging;
|
||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Components.Server;
|
||||||
|
using ILogger = DotBased.Logging.ILogger;
|
||||||
|
|
||||||
|
namespace DotBased.ASP.Auth;
|
||||||
|
|
||||||
|
// RevalidatingServerAuthenticationStateProvider
|
||||||
|
// AuthenticationStateProvider
|
||||||
|
public class BasedServerAuthenticationStateProvider : ServerAuthenticationStateProvider
|
||||||
|
{
|
||||||
|
public BasedServerAuthenticationStateProvider(BasedAuthConfiguration configuration, ISessionStateProvider stateProvider)
|
||||||
|
{
|
||||||
|
_config = configuration;
|
||||||
|
_stateProvider = stateProvider;
|
||||||
|
_logger = LogService.RegisterLogger(typeof(BasedServerAuthenticationStateProvider));
|
||||||
|
}
|
||||||
|
|
||||||
|
private BasedAuthConfiguration _config;
|
||||||
|
private ISessionStateProvider _stateProvider;
|
||||||
|
private ILogger _logger;
|
||||||
|
private readonly AuthenticationState _anonState = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>() {new Claim(ClaimTypes.Role, "test")})));
|
||||||
|
|
||||||
|
public override Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||||
|
{
|
||||||
|
return Task.FromResult(_anonState);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
using DotBased.ASP.Auth.Scheme;
|
using DotBased.ASP.Auth.Scheme;
|
||||||
|
using DotBased.ASP.Auth.Services;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
@ -10,19 +12,49 @@ public static class DotBasedAuthDependencyInjection
|
||||||
/// Use the DotBased authentication implementation
|
/// Use the DotBased authentication implementation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>Use the app.UseAuthentication() and app.UseAuthorization()!</remarks>
|
/// <remarks>Use the app.UseAuthentication() and app.UseAuthorization()!</remarks>
|
||||||
/// <param name="services">Service colllection</param>
|
/// <param name="services">Service collection</param>
|
||||||
/// <param name="configurationAction">DotBased auth configuration</param>
|
/// <param name="configurationAction">DotBased auth configuration</param>
|
||||||
public static void UseBasedAuth(this IServiceCollection services, Action<BasedAuthConfiguration>? configurationAction = null)
|
public static IServiceCollection AddBasedServerAuth(this IServiceCollection services, Action<BasedAuthConfiguration>? configurationAction = null)
|
||||||
{
|
{
|
||||||
var config = new BasedAuthConfiguration();
|
/*var authBuilder = new BasedAuthBuilder(services, configurationAction);
|
||||||
configurationAction?.Invoke(config);
|
return authBuilder;*/
|
||||||
services.AddSingleton<BasedAuthConfiguration>(config);
|
var Configuration = new BasedAuthConfiguration();
|
||||||
|
configurationAction?.Invoke(Configuration);
|
||||||
|
|
||||||
services.AddScoped<AuthenticationStateProvider, BasedAuthenticationStateProvider>();
|
services.AddSingleton<BasedAuthConfiguration>(Configuration);
|
||||||
|
if (Configuration.AuthDataProviderType == null)
|
||||||
|
throw new ArgumentNullException(nameof(Configuration.AuthDataProviderType), $"No '{nameof(IAuthDataProvider)}' configured!");
|
||||||
|
services.AddScoped(typeof(IAuthDataProvider), Configuration.AuthDataProviderType);
|
||||||
|
if (Configuration.SessionStateProviderType == null)
|
||||||
|
throw new ArgumentNullException(nameof(Configuration.SessionStateProviderType), $"No '{nameof(ISessionStateProvider)}' configured!");
|
||||||
|
services.AddScoped(typeof(ISessionStateProvider), Configuration.SessionStateProviderType);
|
||||||
|
|
||||||
|
services.AddScoped<AuthService>();
|
||||||
|
|
||||||
|
services.AddScoped<AuthenticationStateProvider, BasedServerAuthenticationStateProvider>();
|
||||||
services.AddAuthentication(options =>
|
services.AddAuthentication(options =>
|
||||||
{
|
{
|
||||||
options.DefaultScheme = BasedAuthenticationHandler.AuthenticationScheme;
|
options.DefaultScheme = BasedAuthenticationHandler.AuthenticationScheme;
|
||||||
}).AddScheme<BasedAuthenticationHandlerOptions, BasedAuthenticationHandler>(BasedAuthenticationHandler.AuthenticationScheme, null);
|
}).AddScheme<BasedAuthenticationHandlerOptions, BasedAuthenticationHandler>(BasedAuthenticationHandler.AuthenticationScheme, null);
|
||||||
services.AddAuthorization();
|
services.AddAuthorization();
|
||||||
|
services.AddCascadingAuthenticationState();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebApplication UseBasedServerAuth(this WebApplication app)
|
||||||
|
{
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
// Data
|
||||||
|
var authConfig = app.Services.GetService<BasedAuthConfiguration>();
|
||||||
|
if (authConfig == null)
|
||||||
|
throw new NullReferenceException($"{nameof(BasedAuthConfiguration)} is null!");
|
||||||
|
if (authConfig.AuthDataProviderType == null)
|
||||||
|
throw new NullReferenceException($"{nameof(authConfig.AuthDataProviderType)} is null, cannot instantiate an instance of {nameof(IAuthDataProvider)}");
|
||||||
|
var dataProvider = (IAuthDataProvider?)Activator.CreateInstance(authConfig.AuthDataProviderType);
|
||||||
|
if (dataProvider != null) authConfig.SeedData?.Invoke(dataProvider);
|
||||||
|
|
||||||
|
return app;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,7 +32,4 @@ public interface IAuthDataProvider
|
||||||
public Task<Result> UpdateAuthenticationStateAsync(AuthenticationStateModel authenticationState);
|
public Task<Result> UpdateAuthenticationStateAsync(AuthenticationStateModel authenticationState);
|
||||||
public Task<Result> DeleteAuthenticationStateAsync(AuthenticationStateModel authenticationState);
|
public Task<Result> DeleteAuthenticationStateAsync(AuthenticationStateModel authenticationState);
|
||||||
public Task<Result<AuthenticationStateModel>> GetAuthenticationStateAsync(string id);
|
public Task<Result<AuthenticationStateModel>> GetAuthenticationStateAsync(string id);
|
||||||
|
|
||||||
// Authorization
|
|
||||||
|
|
||||||
}
|
}
|
8
DotBased.ASP.Auth/ISessionStateProvider.cs
Normal file
8
DotBased.ASP.Auth/ISessionStateProvider.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace DotBased.ASP.Auth;
|
||||||
|
|
||||||
|
public interface ISessionStateProvider
|
||||||
|
{
|
||||||
|
public const string SessionStateName = "BasedServerSession";
|
||||||
|
public Task<Result<string>> GetSessionStateAsync();
|
||||||
|
public Task<Result> SetSessionStateAsync(string state);
|
||||||
|
}
|
83
DotBased.ASP.Auth/MemoryAuthDataProvider.cs
Normal file
83
DotBased.ASP.Auth/MemoryAuthDataProvider.cs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
using DotBased.ASP.Auth.Domains.Auth;
|
||||||
|
using DotBased.ASP.Auth.Domains.Identity;
|
||||||
|
|
||||||
|
namespace DotBased.ASP.Auth;
|
||||||
|
/// <summary>
|
||||||
|
/// In memory data provider, for testing only!
|
||||||
|
/// </summary>
|
||||||
|
public class MemoryAuthDataProvider : IAuthDataProvider
|
||||||
|
{
|
||||||
|
private Dictionary<string, UserModel> _userDict = [];
|
||||||
|
private Dictionary<string, GroupModel> _groupDict = [];
|
||||||
|
private Dictionary<string, AuthenticationStateModel> _authenticationDict = [];
|
||||||
|
|
||||||
|
public async Task<Result> CreateUserAsync(UserModel user)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> UpdateUserAsync(UserModel user)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> DeleteUserAsync(UserModel user)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<UserModel>> GetUserAsync(string id, string email, string username)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ListResult<UserItemModel>> GetUsersAsync(int start = 0, int amount = 30, string search = "")
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> CreateGroupAsync(GroupModel group)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> UpdateGroupAsync(GroupModel group)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> DeleteGroupAsync(GroupModel group)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<GroupModel>> GetGroupAsync(string id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ListResult<GroupItemModel>> GetGroupsAsync(int start = 0, int amount = 30, string search = "")
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> CreateAuthenticationStateAsync(AuthenticationStateModel authenticationState)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> UpdateAuthenticationStateAsync(AuthenticationStateModel authenticationState)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> DeleteAuthenticationStateAsync(AuthenticationStateModel authenticationState)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<AuthenticationStateModel>> GetAuthenticationStateAsync(string id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
43
DotBased.ASP.Auth/Services/AuthService.cs
Normal file
43
DotBased.ASP.Auth/Services/AuthService.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
using DotBased.ASP.Auth.Domains;
|
||||||
|
using DotBased.ASP.Auth.Domains.Auth;
|
||||||
|
using DotBased.Extensions;
|
||||||
|
using DotBased.Logging;
|
||||||
|
|
||||||
|
namespace DotBased.ASP.Auth.Services;
|
||||||
|
|
||||||
|
public class AuthService
|
||||||
|
{
|
||||||
|
public AuthService(IAuthDataProvider dataProvider)
|
||||||
|
{
|
||||||
|
_dataProvider = dataProvider;
|
||||||
|
_logger = LogService.RegisterLogger(typeof(AuthService));
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IAuthDataProvider _dataProvider;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public async Task<Result<AuthenticationStateModel>> LoginAsync(LoginModel login)
|
||||||
|
{
|
||||||
|
if (login.UserName.IsNullOrWhiteSpace())
|
||||||
|
return Result<AuthenticationStateModel>.Failed("Username argument is empty!");
|
||||||
|
var userResult = await _dataProvider.GetUserAsync(string.Empty, login.Email, login.UserName);
|
||||||
|
//TODO: validate user password and create a session state
|
||||||
|
return Result<AuthenticationStateModel>.Failed("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> Logout(string state)
|
||||||
|
{
|
||||||
|
if (state.IsNullOrWhiteSpace())
|
||||||
|
return Result.Failed($"Argument {nameof(state)} is empty!");
|
||||||
|
var stateResult = await _dataProvider.GetAuthenticationStateAsync(state);
|
||||||
|
if (!stateResult.Success || stateResult.Value == null)
|
||||||
|
return stateResult;
|
||||||
|
var authState = stateResult.Value;
|
||||||
|
//TODO: Update state to logged out and update the state
|
||||||
|
|
||||||
|
var updatedStateResult = await _dataProvider.UpdateAuthenticationStateAsync(authState);
|
||||||
|
if (updatedStateResult.Success) return updatedStateResult;
|
||||||
|
_logger.Warning(updatedStateResult.Message);
|
||||||
|
return updatedStateResult;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user