From 217c55df00b416967486bdceb5a68bd8f82e16a4 Mon Sep 17 00:00:00 2001 From: max Date: Sun, 18 May 2025 18:03:40 +0200 Subject: [PATCH] [WIP] --- .../AuthorityDefaults.cs | 8 +++++ .../Controllers/AuthorityController.cs | 34 ++++++++++++++++--- .../AuthorityLoginAuthenticationHandler.cs | 5 +-- .../Models/Data/System/AboutModel.cs | 10 ------ .../Data/System/AuthorityInformation.cs | 25 ++++++++++++++ .../Auth/AuthorityAuthenticationOptions.cs | 1 + .../AuthorityAuthenticationService.cs | 2 +- TestWebApi/Program.cs | 12 ++++--- 8 files changed, 75 insertions(+), 22 deletions(-) delete mode 100644 DotBased.AspNet.Authority/Models/Data/System/AboutModel.cs create mode 100644 DotBased.AspNet.Authority/Models/Data/System/AuthorityInformation.cs diff --git a/DotBased.AspNet.Authority/AuthorityDefaults.cs b/DotBased.AspNet.Authority/AuthorityDefaults.cs index 43568c4..981d0f7 100755 --- a/DotBased.AspNet.Authority/AuthorityDefaults.cs +++ b/DotBased.AspNet.Authority/AuthorityDefaults.cs @@ -27,6 +27,14 @@ public static class AuthorityDefaults public const string Default = "/"; public const string Login = "/auth/login"; public const string Logout = "/auth/logout"; + public const string Challenge = "/auth/challenge"; public const string Forbidden = "/forbidden"; + public const string Info = "/info"; + } + + public static class ClaimTypes + { + public const string Attribute = "Authority.Attribute"; + public const string AuthenticatedScheme = "Authority.Scheme.Authenticated"; } } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Controllers/AuthorityController.cs b/DotBased.AspNet.Authority/Controllers/AuthorityController.cs index 2e0ffc8..9856ecf 100644 --- a/DotBased.AspNet.Authority/Controllers/AuthorityController.cs +++ b/DotBased.AspNet.Authority/Controllers/AuthorityController.cs @@ -1,4 +1,6 @@ using System.Text.Json; +using DotBased.AspNet.Authority.Models.Data.System; +using DotBased.AspNet.Authority.Services; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -9,7 +11,7 @@ namespace DotBased.AspNet.Authority.Controllers; [Route("[controller]")] public class AuthorityController(IAuthenticationService authenticationService) : ControllerBase { - [HttpGet("auth/login")] + [HttpGet(AuthorityDefaults.Paths.Login)] [AllowAnonymous] public async Task LoginFromSchemeAsync([FromQuery(Name = "s")] string? scheme, [FromQuery(Name = "ss")] string? sessionScheme) { @@ -17,17 +19,41 @@ public class AuthorityController(IAuthenticationService authenticationService) : return Ok(); } - [HttpGet("auth/logout")] + [HttpGet(AuthorityDefaults.Paths.Challenge)] + [AllowAnonymous] + public IActionResult ChallengeLogin([FromQuery(Name = "s")] string? scheme, [FromQuery(Name = "returnUrl")] string returnUrl = "/") + { + return Challenge(scheme, returnUrl); + } + + [HttpGet(AuthorityDefaults.Paths.Logout)] public async Task LogoutAsync() { await HttpContext.SignOutAsync(); return Ok(); } - [HttpGet("info")] + [HttpGet(AuthorityDefaults.Paths.Info)] [AllowAnonymous] public async Task> GetAuthorityInfoAsync() { - return Ok(); + if (authenticationService is not AuthorityAuthenticationService authService) + { + return BadRequest(); + } + + var schemesInfos = authService.GetAllSchemeInfos(); + + var info = new AuthorityInformation + { + IsAuthenticated = false, + SchemeInformation = new SchemeInformation + { + DefaultScheme = authService.Options.DefaultScheme ?? "Unknown", + AvailableSchemes = schemesInfos.ToList() + } + }; + + return Ok(info); } } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Handlers/AuthorityLoginAuthenticationHandler.cs b/DotBased.AspNet.Authority/Handlers/AuthorityLoginAuthenticationHandler.cs index dc65a0a..8923473 100644 --- a/DotBased.AspNet.Authority/Handlers/AuthorityLoginAuthenticationHandler.cs +++ b/DotBased.AspNet.Authority/Handlers/AuthorityLoginAuthenticationHandler.cs @@ -19,8 +19,9 @@ public class AuthorityLoginAuthenticationHandler(IOptionsMonitor HandleAuthenticateAsync() { - var ticket = new AuthenticationTicket(new ClaimsPrincipal(), Scheme.Name); - var result = AuthenticateResult.Success(ticket); + //TODO: Check headers for login credentials. + /*var ticket = new AuthenticationTicket(new ClaimsPrincipal(), Scheme.Name);*/ + var result = AuthenticateResult.Fail("No login found!"); return result; } } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Models/Data/System/AboutModel.cs b/DotBased.AspNet.Authority/Models/Data/System/AboutModel.cs deleted file mode 100644 index 65dd126..0000000 --- a/DotBased.AspNet.Authority/Models/Data/System/AboutModel.cs +++ /dev/null @@ -1,10 +0,0 @@ -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 AuthenticationTypes { get; set; } = []; - public List SessionTypes { get; set; } = []; -} \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Models/Data/System/AuthorityInformation.cs b/DotBased.AspNet.Authority/Models/Data/System/AuthorityInformation.cs new file mode 100644 index 0000000..8457f4f --- /dev/null +++ b/DotBased.AspNet.Authority/Models/Data/System/AuthorityInformation.cs @@ -0,0 +1,25 @@ +using DotBased.AspNet.Authority.Models.Data.Auth; +using DotBased.AspNet.Authority.Models.Options.Auth; + +namespace DotBased.AspNet.Authority.Models.Data.System; + +public class AuthorityInformation +{ + public string ServerName { get; set; } = "Authority.Server"; + public bool IsAuthenticated { get; set; } + public List AuthenticationTypes { get; set; } = []; + public List SessionTypes { get; set; } = []; + public SchemeInformation? SchemeInformation { get; set; } + public AuthenticatedInformation? AuthenticatedInformation { get; set; } +} + +public class SchemeInformation +{ + public string? DefaultScheme { get; set; } + public List AvailableSchemes { get; set; } = []; +} + +public class AuthenticatedInformation +{ + public string? AuthenticatedScheme { get; set; } +} \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Models/Options/Auth/AuthorityAuthenticationOptions.cs b/DotBased.AspNet.Authority/Models/Options/Auth/AuthorityAuthenticationOptions.cs index 297216d..f45affc 100644 --- a/DotBased.AspNet.Authority/Models/Options/Auth/AuthorityAuthenticationOptions.cs +++ b/DotBased.AspNet.Authority/Models/Options/Auth/AuthorityAuthenticationOptions.cs @@ -22,6 +22,7 @@ public class SchemeInfo public string Description { get; set; } = string.Empty; public SchemeType Type { get; set; } public string AuthenticationType { get; set; } = string.Empty; + public string? Endpoint { get; set; } } public enum SchemeType diff --git a/DotBased.AspNet.Authority/Services/AuthorityAuthenticationService.cs b/DotBased.AspNet.Authority/Services/AuthorityAuthenticationService.cs index c66c539..5a83302 100644 --- a/DotBased.AspNet.Authority/Services/AuthorityAuthenticationService.cs +++ b/DotBased.AspNet.Authority/Services/AuthorityAuthenticationService.cs @@ -27,7 +27,7 @@ public class AuthorityAuthenticationService( return base.AuthenticateAsync(context, scheme); } - // Trigger login + // Trigger login - Redirects to provider (OIDC, etc.) // Used when access to a resource requires authentication, but the user has not provided valid credentials. public override Task ChallengeAsync(HttpContext context, string? scheme, AuthenticationProperties? properties) { diff --git a/TestWebApi/Program.cs b/TestWebApi/Program.cs index e5aa9c3..02aab28 100755 --- a/TestWebApi/Program.cs +++ b/TestWebApi/Program.cs @@ -33,23 +33,25 @@ builder.Services.AddAuthority() .MapAuthorityEndpoints() .AddAuthorityAuth(options => { - options.DefaultScheme = AuthorityDefaults.Scheme.Cookie.AuthenticationScheme; - options.DefaultSignInScheme = AuthorityDefaults.Scheme.Authority.AuthenticationScheme; - options.DefaultSignOutScheme = AuthorityDefaults.Scheme.Authority.AuthenticationScheme; + options.DefaultScheme = AuthorityDefaults.Scheme.Authority.AuthenticationScheme; + options.DefaultSignInScheme = AuthorityDefaults.Scheme.Cookie.AuthenticationScheme; + options.DefaultSignOutScheme = AuthorityDefaults.Scheme.Cookie.AuthenticationScheme; options.SchemeInfoMap = [ new SchemeInfo { Scheme = AuthorityDefaults.Scheme.Authority.AuthenticationScheme, Description = "Authority password login", Type = SchemeType.Authentication, - AuthenticationType = "Password" + AuthenticationType = "Password", + Endpoint = AuthorityDefaults.Paths.Login }, /*new SchemeInfo { Scheme = "OIDC", Description = "Authentik OIDC login", Type = SchemeType.Authentication, - AuthenticationType = "OpenIdConnect" + AuthenticationType = "OpenIdConnect", + Endpoint = AuthorityDefaults.Paths.Challenge },*/ new SchemeInfo {