[CHANGE] Reworking auth schemes & services, handlers, etc.

This commit is contained in:
max
2025-04-27 17:23:14 +02:00
parent 8e72d123fd
commit 46cf20893b
15 changed files with 249 additions and 64 deletions

View File

@@ -4,8 +4,24 @@ public static class AuthorityDefaults
{
public static class Scheme
{
public const string AuthenticationScheme = "Authority.Scheme.Authentication";
public const string ExternalScheme = "Authority.Scheme.External";
public static class Cookie
{
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";
}
}

View File

@@ -1,7 +1,10 @@
using DotBased.AspNet.Authority.Crypto;
using DotBased.AspNet.Authority.Managers;
using DotBased.AspNet.Authority.Models.Options;
using DotBased.AspNet.Authority.Models.Options.Auth;
using DotBased.AspNet.Authority.Services;
using DotBased.AspNet.Authority.Validators;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -9,13 +12,13 @@ namespace DotBased.AspNet.Authority;
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();
services.Configure<AuthorityOptions>(optionsAction);
}
services.AddOptions();
ArgumentNullException.ThrowIfNull(optionsAction);
services.Configure(optionsAction);
services.TryAddScoped<ICryptographer, Cryptographer>();
services.TryAddScoped<IPasswordHasher, PasswordHasher>();
@@ -26,9 +29,49 @@ public static class AuthorityProviderExtensions
services.TryAddScoped<IPhoneNumberVerifier, PhoneNumberVerifier>();
services.TryAddScoped<IUserVerifier, UserVerifier>();*/
services.TryAddScoped<AuthorityManager>();
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
{
return authorityBuilder;
@@ -38,20 +81,4 @@ public static class AuthorityProviderExtensions
{
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));
}
}

View File

@@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Mvc;
namespace DotBased.AspNet.Authority.Controllers;
[ApiController]
[Route("[controller]")]
public class AuthorityController : ControllerBase
{
}

View File

@@ -17,11 +17,14 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Models\Data\" />
<Folder Include="Models\Security\" />
<Folder Include="Schemas\" />
</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" />
</ItemGroup>

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View 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; } = [];
}

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -0,0 +1,6 @@
namespace DotBased.AspNet.Authority.Models.Options.Auth;
public class SessionOptions
{
public TimeSpan RefreshInterval { get; set; } = TimeSpan.FromMinutes(30);
}

View File

@@ -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);
}
}