mirror of
https://github.com/hmaxnl/DotBased.git
synced 2025-05-16 07:17:54 +02:00
[CHANGE] Reworking auth schemes & services, handlers, etc.
This commit is contained in:
parent
8e72d123fd
commit
46cf20893b
|
@ -7,13 +7,13 @@ namespace DotBased.AspNet.Authority.EFCore;
|
||||||
|
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddAuthorityContext(this IServiceCollection services, Action<DbContextOptionsBuilder> options)
|
public static AuthorityBuilder AddAuthorityContext(this AuthorityBuilder builder, Action<DbContextOptionsBuilder> options)
|
||||||
{
|
{
|
||||||
services.AddDbContextFactory<AuthorityContext>(options);
|
builder.Services.AddDbContextFactory<AuthorityContext>(options);
|
||||||
services.AddScoped<IAttributeRepository, AttributeRepository>();
|
builder.Services.AddScoped<IAttributeRepository, AttributeRepository>();
|
||||||
services.AddScoped<IGroupRepository, GroupRepository>();
|
builder.Services.AddScoped<IGroupRepository, GroupRepository>();
|
||||||
services.AddScoped<IRoleRepository, RoleRepository>();
|
builder.Services.AddScoped<IRoleRepository, RoleRepository>();
|
||||||
services.AddScoped<IUserRepository, UserRepository>();
|
builder.Services.AddScoped<IUserRepository, UserRepository>();
|
||||||
return services;
|
return builder;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,8 +4,24 @@ public static class AuthorityDefaults
|
||||||
{
|
{
|
||||||
public static class Scheme
|
public static class Scheme
|
||||||
{
|
{
|
||||||
public const string AuthenticationScheme = "Authority.Scheme.Authentication";
|
public static class Cookie
|
||||||
public const string ExternalScheme = "Authority.Scheme.External";
|
{
|
||||||
|
public const string Default = "Authority.Scheme.Cookie";
|
||||||
|
public const string CookieName = "AuthorityAuth";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Token
|
||||||
|
{
|
||||||
|
public const string Default = "Authority.Scheme.Token";
|
||||||
|
public const string TokenName = "AuthorityAuthToken";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Paths
|
||||||
|
{
|
||||||
|
public const string Default = "/";
|
||||||
|
public const string Login = "/auth/login";
|
||||||
|
public const string Logout = "/auth/logout";
|
||||||
|
public const string Forbidden = "/forbidden";
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
using DotBased.AspNet.Authority.Crypto;
|
using DotBased.AspNet.Authority.Crypto;
|
||||||
using DotBased.AspNet.Authority.Managers;
|
using DotBased.AspNet.Authority.Managers;
|
||||||
using DotBased.AspNet.Authority.Models.Options;
|
using DotBased.AspNet.Authority.Models.Options;
|
||||||
|
using DotBased.AspNet.Authority.Models.Options.Auth;
|
||||||
|
using DotBased.AspNet.Authority.Services;
|
||||||
using DotBased.AspNet.Authority.Validators;
|
using DotBased.AspNet.Authority.Validators;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
|
||||||
|
@ -9,13 +12,13 @@ namespace DotBased.AspNet.Authority;
|
||||||
|
|
||||||
public static class AuthorityProviderExtensions
|
public static class AuthorityProviderExtensions
|
||||||
{
|
{
|
||||||
public static AuthorityBuilder AddAuthority(this IServiceCollection services, Action<AuthorityOptions>? optionsAction = null)
|
public static AuthorityBuilder AddAuthority(this IServiceCollection services) => AddAuthority(services, _ => { });
|
||||||
|
|
||||||
|
public static AuthorityBuilder AddAuthority(this IServiceCollection services, Action<AuthorityOptions> optionsAction)
|
||||||
{
|
{
|
||||||
if (optionsAction != null)
|
services.AddOptions();
|
||||||
{
|
ArgumentNullException.ThrowIfNull(optionsAction);
|
||||||
services.AddOptions();
|
services.Configure(optionsAction);
|
||||||
services.Configure<AuthorityOptions>(optionsAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
services.TryAddScoped<ICryptographer, Cryptographer>();
|
services.TryAddScoped<ICryptographer, Cryptographer>();
|
||||||
services.TryAddScoped<IPasswordHasher, PasswordHasher>();
|
services.TryAddScoped<IPasswordHasher, PasswordHasher>();
|
||||||
|
@ -26,9 +29,49 @@ public static class AuthorityProviderExtensions
|
||||||
services.TryAddScoped<IPhoneNumberVerifier, PhoneNumberVerifier>();
|
services.TryAddScoped<IPhoneNumberVerifier, PhoneNumberVerifier>();
|
||||||
services.TryAddScoped<IUserVerifier, UserVerifier>();*/
|
services.TryAddScoped<IUserVerifier, UserVerifier>();*/
|
||||||
services.TryAddScoped<AuthorityManager>();
|
services.TryAddScoped<AuthorityManager>();
|
||||||
|
|
||||||
return new AuthorityBuilder(services);
|
return new AuthorityBuilder(services);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AuthenticationBuilder AddAuthorityAuth(this AuthorityBuilder builder) => AddAuthorityAuth(builder, _ => { });
|
||||||
|
|
||||||
|
public static AuthenticationBuilder AddAuthorityAuth(this AuthorityBuilder builder, Action<AuthorityAuthenticationOptions> configureOptions)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(configureOptions);
|
||||||
|
builder.Services.Configure(configureOptions);
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IAuthenticationService, AuthorityAuthenticationService>();
|
||||||
|
var authBuilder = builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
|
||||||
|
});
|
||||||
|
return authBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AuthenticationBuilder AddAuthorityCookie(this AuthenticationBuilder builder, string scheme = AuthorityDefaults.Scheme.Cookie.Default)
|
||||||
|
{
|
||||||
|
builder.AddCookie(options =>
|
||||||
|
{
|
||||||
|
options.Cookie.Name = AuthorityDefaults.Scheme.Cookie.CookieName;
|
||||||
|
options.Cookie.Path = AuthorityDefaults.Paths.Default;
|
||||||
|
options.Cookie.Expiration = TimeSpan.FromDays(1);
|
||||||
|
options.Cookie.HttpOnly = true;
|
||||||
|
options.Cookie.IsEssential = true;
|
||||||
|
options.LoginPath = AuthorityDefaults.Paths.Login;
|
||||||
|
options.LogoutPath = AuthorityDefaults.Paths.Logout;
|
||||||
|
options.AccessDeniedPath = AuthorityDefaults.Paths.Forbidden;
|
||||||
|
options.SlidingExpiration = true;
|
||||||
|
//options.SessionStore
|
||||||
|
});
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AuthenticationBuilder AddAuthorityToken(this AuthenticationBuilder builder, string scheme = AuthorityDefaults.Scheme.Token.Default)
|
||||||
|
{
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
public static AuthorityBuilder AddAuthorityRepository<TRepository>(this AuthorityBuilder authorityBuilder) where TRepository : class
|
public static AuthorityBuilder AddAuthorityRepository<TRepository>(this AuthorityBuilder authorityBuilder) where TRepository : class
|
||||||
{
|
{
|
||||||
return authorityBuilder;
|
return authorityBuilder;
|
||||||
|
@ -38,20 +81,4 @@ public static class AuthorityProviderExtensions
|
||||||
{
|
{
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type GetBaseGenericArgumentType<TModel>(Type baseType)
|
|
||||||
{
|
|
||||||
var userGenericBaseTypeDefinition = typeof(TModel).BaseType?.GetGenericTypeDefinition();
|
|
||||||
if (userGenericBaseTypeDefinition != null && userGenericBaseTypeDefinition == baseType)
|
|
||||||
{
|
|
||||||
var userBaseGenericArguments = userGenericBaseTypeDefinition.GetGenericArguments();
|
|
||||||
if (userBaseGenericArguments.Length <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Base implementation does not have the required generic argument.", nameof(TModel));
|
|
||||||
}
|
|
||||||
|
|
||||||
return userBaseGenericArguments[0];
|
|
||||||
}
|
|
||||||
throw new ArgumentException($"Given object {typeof(TModel).Name} does not have the base implementation type of: {baseType.Name}", nameof(TModel));
|
|
||||||
}
|
|
||||||
}
|
}
|
10
DotBased.AspNet.Authority/Controllers/AuthorityController.cs
Normal file
10
DotBased.AspNet.Authority/Controllers/AuthorityController.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class AuthorityController : ControllerBase
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -17,11 +17,14 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Models\Data\" />
|
|
||||||
<Folder Include="Models\Security\" />
|
<Folder Include="Models\Security\" />
|
||||||
|
<Folder Include="Schemas\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.3.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.3.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.3.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.Handlers;
|
||||||
|
|
||||||
|
public class AuthorityAuthenticationHandler : IAuthenticationHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler
|
||||||
|
{
|
||||||
|
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<AuthenticateResult> AuthenticateAsync()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ChallengeAsync(AuthenticationProperties properties)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ForbidAsync(AuthenticationProperties properties)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SignOutAsync(AuthenticationProperties properties)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Data.Auth;
|
||||||
|
|
||||||
|
public class AuthenticationSessionType
|
||||||
|
{
|
||||||
|
public string Id { get; set; } = string.Empty;
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Data.Auth;
|
||||||
|
|
||||||
|
public class AuthenticationType
|
||||||
|
{
|
||||||
|
public string Id { get; set; } = string.Empty;
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Provider { get; set; } = string.Empty;
|
||||||
|
public bool Redirects { get; set; }
|
||||||
|
public AuthenticationTypePaths Paths { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AuthenticationTypePaths
|
||||||
|
{
|
||||||
|
public string Login { get; set; } = string.Empty;
|
||||||
|
public string Logout { get; set; } = string.Empty;
|
||||||
|
}
|
10
DotBased.AspNet.Authority/Models/Data/System/AboutModel.cs
Normal file
10
DotBased.AspNet.Authority/Models/Data/System/AboutModel.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using DotBased.AspNet.Authority.Models.Data.Auth;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Data.System;
|
||||||
|
|
||||||
|
public class AboutModel
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "Authority.Server";
|
||||||
|
public List<AuthenticationType> AuthenticationTypes { get; set; } = [];
|
||||||
|
public List<AuthenticationSessionType> SessionTypes { get; set; } = [];
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Options.Auth;
|
||||||
|
|
||||||
|
public class AuthenticationSecurityOptions
|
||||||
|
{
|
||||||
|
public SecurityMode SecurityMode { get; set; } = SecurityMode.Normal;
|
||||||
|
public List<string> AllowedLoginMethods { get; set; } = ["*"];
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SecurityMode
|
||||||
|
{
|
||||||
|
Loose = 0,
|
||||||
|
Normal = 1,
|
||||||
|
Strict = 2
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Options.Auth;
|
||||||
|
|
||||||
|
public class AuthorityAuthenticationOptions
|
||||||
|
{
|
||||||
|
public AuthenticationSecurityOptions Security { get; set; } = new AuthenticationSecurityOptions();
|
||||||
|
public SessionOptions Session { get; set; } = new SessionOptions();
|
||||||
|
public string DefaultScheme { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Options.Auth;
|
||||||
|
|
||||||
|
public class SessionOptions
|
||||||
|
{
|
||||||
|
public TimeSpan RefreshInterval { get; set; } = TimeSpan.FromMinutes(30);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.Services;
|
||||||
|
|
||||||
|
public class AuthorityAuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticationHandlerProvider handlers, IClaimsTransformation transform) : AuthenticationService(schemes, handlers, transform)
|
||||||
|
{
|
||||||
|
public override Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
|
||||||
|
{
|
||||||
|
//TODO: Get from query parameters which auth scheme to use or fallback to configured default.
|
||||||
|
return base.SignInAsync(context, scheme, principal, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
|
||||||
|
{
|
||||||
|
//TODO: Figure out which type of auth is used and logout with the scheme.
|
||||||
|
return base.SignOutAsync(context, scheme, properties);
|
||||||
|
}
|
||||||
|
}
|
30
TestWebApi/Controllers/WeatherController.cs
Normal file
30
TestWebApi/Controllers/WeatherController.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace TestWebApi.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
[Authorize]
|
||||||
|
public class WeatherController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly string[] _summaries =
|
||||||
|
[
|
||||||
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||||
|
];
|
||||||
|
|
||||||
|
[HttpGet("GetWeatherForecast")]
|
||||||
|
public async Task<ActionResult<List<WeatherForecast>>> GetForecast()
|
||||||
|
{
|
||||||
|
var forecast = Enumerable.Range(1, 5).Select(index =>
|
||||||
|
new WeatherForecast
|
||||||
|
(
|
||||||
|
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||||
|
Random.Shared.Next(-20, 55),
|
||||||
|
_summaries[Random.Shared.Next(_summaries.Length)]
|
||||||
|
))
|
||||||
|
.ToList();
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||||
|
return forecast;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,20 +21,15 @@ LogService.AddLogAdapter(new BasedSerilogAdapter(serilogLogger));
|
||||||
|
|
||||||
builder.Logging.ClearProviders();
|
builder.Logging.ClearProviders();
|
||||||
builder.Logging.AddDotBasedLoggerProvider(LogService.Options);
|
builder.Logging.AddDotBasedLoggerProvider(LogService.Options);
|
||||||
builder.Services.AddAuthorityContext(options =>
|
|
||||||
{
|
|
||||||
options.UseSqlite("Data Source=dev-dotbased.db", c => c.MigrationsAssembly("TestWebApi"));
|
|
||||||
});
|
|
||||||
builder.Services.AddAuthority(options =>
|
|
||||||
{
|
|
||||||
|
|
||||||
});
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
/*builder.Services.AddAuthentication(options =>
|
builder.Services.AddAuthority().AddAuthorityContext(options =>
|
||||||
{
|
{
|
||||||
options.DefaultScheme = BasedAuthenticationDefaults.BasedAuthenticationScheme;
|
options.UseSqlite("Data Source=dev-authority.db", c => c.MigrationsAssembly("TestWebApi"));
|
||||||
options.DefaultChallengeScheme = BasedAuthenticationDefaults.BasedAuthenticationScheme;
|
}).AddAuthorityAuth()
|
||||||
}).AddCookie();*/
|
.AddAuthorityCookie()
|
||||||
|
.AddAuthorityToken();
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
@ -53,28 +48,13 @@ if (app.Environment.IsDevelopment())
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
var summaries = new[]
|
app.UseAuthentication();
|
||||||
{
|
app.UseAuthorization();
|
||||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
|
||||||
};
|
|
||||||
|
|
||||||
app.MapGet("/weatherforecast", () =>
|
|
||||||
{
|
|
||||||
var forecast = Enumerable.Range(1, 5).Select(index =>
|
|
||||||
new WeatherForecast
|
|
||||||
(
|
|
||||||
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
|
||||||
Random.Shared.Next(-20, 55),
|
|
||||||
summaries[Random.Shared.Next(summaries.Length)]
|
|
||||||
))
|
|
||||||
.ToArray();
|
|
||||||
return forecast;
|
|
||||||
})
|
|
||||||
.WithName("GetWeatherForecast")
|
|
||||||
.WithOpenApi();
|
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
return;
|
||||||
|
|
||||||
ILogger SetupSerilog()
|
ILogger SetupSerilog()
|
||||||
{
|
{
|
||||||
|
@ -84,7 +64,7 @@ ILogger SetupSerilog()
|
||||||
return logConfig.CreateLogger();
|
return logConfig.CreateLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
|
public record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
|
||||||
{
|
{
|
||||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user