diff --git a/DotBased.AspNet.Authority/Models/Options/Auth/AuthorityAuthenticationOptions.cs b/DotBased.AspNet.Authority/Models/Options/Auth/AuthorityAuthenticationOptions.cs index 15563a9..9f2a4f4 100644 --- a/DotBased.AspNet.Authority/Models/Options/Auth/AuthorityAuthenticationOptions.cs +++ b/DotBased.AspNet.Authority/Models/Options/Auth/AuthorityAuthenticationOptions.cs @@ -5,6 +5,11 @@ public class AuthorityAuthenticationOptions public AuthenticationSecurityOptions Security { get; set; } = new AuthenticationSecurityOptions(); public SessionOptions Session { get; set; } = new SessionOptions(); public string DefaultScheme { get; set; } = string.Empty; + public string DefaultAuthenticateScheme { get; set; } = string.Empty; + public string DefaultChallengeScheme { get; set; } = string.Empty; + public string DefaultForbidScheme { get; set; } = string.Empty; + public string DefaultSignInScheme { get; set; } = string.Empty; + public string DefaultSignOutScheme { get; set; } = string.Empty; public List SchemeMap { get; set; } = []; } diff --git a/DotBased.AspNet.Authority/Services/AuthorityAuthenticationService.cs b/DotBased.AspNet.Authority/Services/AuthorityAuthenticationService.cs index ab31b60..b9556b1 100644 --- a/DotBased.AspNet.Authority/Services/AuthorityAuthenticationService.cs +++ b/DotBased.AspNet.Authority/Services/AuthorityAuthenticationService.cs @@ -1,47 +1,101 @@ using System.Security.Claims; -using DotBased.AspNet.Authority.Managers; using DotBased.AspNet.Authority.Models.Options.Auth; +using DotBased.Logging; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; namespace DotBased.AspNet.Authority.Services; -public class AuthorityAuthenticationService(IAuthenticationSchemeProvider schemes, +public class AuthorityAuthenticationService( IAuthenticationHandlerProvider handlers, IClaimsTransformation transform, - IOptions options, - AuthorityManager manager) : IAuthenticationService + IOptions options) : IAuthenticationService { + private readonly ILogger _logger = LogService.RegisterLogger(typeof(AuthorityAuthenticationService)); + private readonly AuthorityAuthenticationOptions _options = options.Value; + public async Task AuthenticateAsync(HttpContext context, string scheme) { - throw new NotImplementedException(); + _logger.Debug("Authenticate with scheme: {Scheme}", scheme); + + var authenticationHandler = await GetAuthenticationHandler(context, scheme, _options.DefaultAuthenticateScheme); + var authResult = await authenticationHandler.AuthenticateAsync(); + + return authResult is { Succeeded: true } + ? AuthenticateResult.Success( + new AuthenticationTicket(await transform.TransformAsync(authResult.Principal), authResult.Properties, authResult.Ticket.AuthenticationScheme)) : + AuthenticateResult.Fail("Failed to authenticate"); } public async Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties) { - throw new NotImplementedException(); + _logger.Debug("Challenging with scheme: {Scheme}", scheme); + + var authenticationHandler = await GetAuthenticationHandler(context, scheme, _options.DefaultChallengeScheme); + await authenticationHandler.ChallengeAsync(properties); } public async Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties) { - throw new NotImplementedException(); + _logger.Debug("Forbid with scheme: {Scheme}", scheme); + + var authenticationHandler = await GetAuthenticationHandler(context, scheme, _options.DefaultForbidScheme); + await authenticationHandler.ForbidAsync(properties); } public async Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) { - throw new NotImplementedException(); + _logger.Debug("SignIn with scheme: {Scheme}", scheme); + + var authenticationHandler = await GetAuthenticationHandler(context, scheme, _options.DefaultSignInScheme); + if (authenticationHandler is not IAuthenticationSignInHandler signInHandler) + { + throw new InvalidOperationException("Authentication handler is not a IAuthenticationSignInHandler."); + } + await signInHandler.SignInAsync(principal, properties); } public async Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties) { - throw new NotImplementedException(); + _logger.Debug("SignOut with scheme: {Scheme}", scheme); + + var authenticationHandler = await GetAuthenticationHandler(context, scheme, _options.DefaultSignOutScheme); + if (authenticationHandler is not IAuthenticationSignOutHandler signOutHandler) + { + throw new InvalidOperationException("Authentication handler is not a IAuthenticationSignOutHandler."); + } + await signOutHandler.SignOutAsync(properties); } - public async Task ValidateLoginAsync() + /*public async Task ValidateLoginAsync() { - //TODO: Check if user is logged in from external identity provider, if user not exists in authority db create user. throw new NotImplementedException(); + }*/ + + private async Task GetAuthenticationHandler(HttpContext context, string scheme, string defaultScheme) + { + if (string.IsNullOrWhiteSpace(scheme)) + { + scheme = defaultScheme; + if (string.IsNullOrWhiteSpace(scheme)) + { + scheme = _options.DefaultScheme; + if (string.IsNullOrWhiteSpace(scheme)) + { + throw new InvalidOperationException("Failed to get default scheme. No scheme specified."); + } + } + } + + var authenticationHandler = await handlers.GetHandlerAsync(context, scheme); + if (authenticationHandler == null) + { + _logger.Warning("Failed to load handler for scheme: {Scheme}", scheme); + throw new InvalidOperationException($"No authentication handlers registered to the scheme '{scheme}'"); + } + + return authenticationHandler; } } \ No newline at end of file