From a85397a363cade6931d5c7ac1857cc9e7834e502 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 28 Apr 2025 16:49:46 +0200 Subject: [PATCH] =?UTF-8?q?refactor(auth):=20Refactoring=20der=20Login-Met?= =?UTF-8?q?hoden=20f=C3=BCr=20OpenAPI-Kompatibilit=C3=A4t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit – Die Login-Methoden wurden überarbeitet, um NotImplementedException auszulösen und OpenAPI (Swagger) und Skalar zu konfigurieren. – Unnötige using-Anweisungen wurden entfernt, um den Code zu optimieren. --- .../Controllers/AuthController.cs | 307 ++++++++---------- 1 file changed, 129 insertions(+), 178 deletions(-) diff --git a/EnvelopeGenerator.GeneratorAPI/Controllers/AuthController.cs b/EnvelopeGenerator.GeneratorAPI/Controllers/AuthController.cs index 5ce1ce7a..68b4d5c4 100644 --- a/EnvelopeGenerator.GeneratorAPI/Controllers/AuthController.cs +++ b/EnvelopeGenerator.GeneratorAPI/Controllers/AuthController.cs @@ -5,197 +5,148 @@ using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; using System.Security.Claims; -using DigitalData.UserManager.Application.DTOs.Auth; using Microsoft.AspNetCore.Authorization; using EnvelopeGenerator.GeneratorAPI.Models; -namespace EnvelopeGenerator.GeneratorAPI.Controllers +namespace EnvelopeGenerator.GeneratorAPI.Controllers; + +/// +/// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus. +/// +[Route("api/[controller]")] +[ApiController] +public partial class AuthController : ControllerBase { + private readonly ILogger _logger; + private readonly IUserService _userService; + private readonly IDirectorySearchService _dirSearchService; + /// - /// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus. + /// Initializes a new instance of the class. /// - [Route("api/[controller]")] - [ApiController] - public partial class AuthController : ControllerBase + /// The logger instance. + /// The user service instance. + /// The directory search service instance. + public AuthController(ILogger logger, IUserService userService, IDirectorySearchService dirSearchService) { - private readonly ILogger _logger; - private readonly IUserService _userService; - private readonly IDirectorySearchService _dirSearchService; - - /// - /// Initializes a new instance of the class. - /// - /// The logger instance. - /// The user service instance. - /// The directory search service instance. - public AuthController(ILogger logger, IUserService userService, IDirectorySearchService dirSearchService) - { - _logger = logger; - _userService = userService; - _dirSearchService = dirSearchService; - } - - /// - /// Authentifiziert einen Benutzer und generiert ein JWT-Token. Wenn 'cookie' wahr ist, wird das Token als HTTP-Only-Cookie zurückgegeben. - /// - /// Benutzeranmeldedaten (Benutzername und Passwort). - /// Wenn wahr, wird das JWT-Token auch als HTTP-Only-Cookie gesendet. - /// - /// Gibt eine HTTP 200 oder 401. - /// - /// - /// Sample request: - /// - /// POST /api/auth?cookie=true - /// { - /// "username": "MaxMustermann", - /// "password": "Geheim123!" - /// } - /// - /// POST /api/auth?cookie=true - /// { - /// "id": "1", - /// "password": "Geheim123!" - /// } - /// - /// - /// Erfolgreiche Anmeldung. Gibt das JWT-Token im Antwortkörper oder als Cookie zurück, wenn 'cookie' wahr ist. - /// Unbefugt. Ungültiger Benutzername oder Passwort. - [ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")] - [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] - [AllowAnonymous] - [HttpPost] - public async Task Login([FromBody] Login login, [FromQuery] bool cookie = false) - { - try - { - bool isValid = _dirSearchService.ValidateCredentials(login.Username, login.Password); - - if (!isValid) - return Unauthorized(); - - //find the user - var uRes = await _userService.ReadByUsernameAsync(login.Username); - if (!uRes.IsSuccess || uRes.Data is null) - { - return Forbid(); - } - - UserReadDto user = uRes.Data; - - // Create claims - var claims = new List - { - new (ClaimTypes.NameIdentifier, user.Id.ToString()), - new (ClaimTypes.Name, user.Username), - new (ClaimTypes.Surname, user.Name!), - new (ClaimTypes.GivenName, user.Prename!), - new (ClaimTypes.Email, user.Email!), - }; - - // Create claimsIdentity - var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); - - // Create authProperties - var authProperties = new AuthenticationProperties - { - IsPersistent = true, - AllowRefresh = true, - ExpiresUtc = DateTime.Now.AddMinutes(180) - }; + _logger = logger; + _userService = userService; + _dirSearchService = dirSearchService; + } - // Sign in - await HttpContext.SignInAsync( - CookieAuthenticationDefaults.AuthenticationScheme, - new ClaimsPrincipal(claimsIdentity), - authProperties); + /// + /// Authentifiziert einen Benutzer und generiert ein JWT-Token. Wenn 'cookie' wahr ist, wird das Token als HTTP-Only-Cookie zurückgegeben. + /// + /// Benutzeranmeldedaten (Benutzername und Passwort). + /// Wenn wahr, wird das JWT-Token auch als HTTP-Only-Cookie gesendet. + /// + /// Gibt eine HTTP 200 oder 401. + /// + /// + /// Sample request: + /// + /// POST /api/auth?cookie=true + /// { + /// "username": "MaxMustermann", + /// "password": "Geheim123!" + /// } + /// + /// POST /api/auth?cookie=true + /// { + /// "id": "1", + /// "password": "Geheim123!" + /// } + /// + /// + /// Erfolgreiche Anmeldung. Gibt das JWT-Token im Antwortkörper oder als Cookie zurück, wenn 'cookie' wahr ist. + /// Unbefugt. Ungültiger Benutzername oder Passwort. + [ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [AllowAnonymous] + [HttpPost] + public Task Login([FromBody] Login login, [FromQuery] bool cookie = false) + { + // added to configure open API (swagger and scalar) + throw new NotImplementedException(); + } - return Ok(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Unexpected error occurred.\n{ErrorMessage}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } + /// + /// Authentifiziert einen Benutzer und generiert ein JWT-Token. Das Token wird als HTTP-only-Cookie zurückgegeben. + /// + /// Benutzeranmeldedaten (Benutzername und Passwort). + /// + /// Gibt eine HTTP 200 oder 401. + /// + /// + /// Sample request: + /// + /// POST /api/auth/form + /// { + /// "username": "MaxMustermann", + /// "password": "Geheim123!" + /// } + /// + /// + /// Erfolgreiche Anmeldung. Gibt das JWT-Token im Antwortkörper oder als Cookie zurück, wenn 'cookie' wahr ist. + /// Unbefugt. Ungültiger Benutzername oder Passwort. + [ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [AllowAnonymous] + [HttpPost] + [Route("form")] + public Task Login([FromForm] Login login) + { + // added to configure open API (swagger and scalar) + throw new NotImplementedException(); + } - /// - /// Authentifiziert einen Benutzer und generiert ein JWT-Token. Das Token wird als HTTP-only-Cookie zurückgegeben. - /// - /// Benutzeranmeldedaten (Benutzername und Passwort). - /// - /// Gibt eine HTTP 200 oder 401. - /// - /// - /// Sample request: - /// - /// POST /api/auth/form - /// { - /// "username": "MaxMustermann", - /// "password": "Geheim123!" - /// } - /// - /// - /// Erfolgreiche Anmeldung. Gibt das JWT-Token im Antwortkörper oder als Cookie zurück, wenn 'cookie' wahr ist. - /// Unbefugt. Ungültiger Benutzername oder Passwort. - [ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")] - [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] - [AllowAnonymous] - [HttpPost] - [Route("form")] - public async Task Login([FromForm] Login login) + /// + /// Entfernt das Authentifizierungs-Cookie des Benutzers (AuthCookie) + /// + /// + /// Gibt eine HTTP 200 oder 401. + /// + /// + /// Sample request: + /// + /// POST /api/auth/logout + /// + /// + /// Erfolgreich gelöscht, wenn der Benutzer ein berechtigtes Cookie hat. + /// Wenn es kein zugelassenes Cookie gibt, wird „nicht zugelassen“ zurückgegeben. + [ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [Authorize] + [HttpPost("logout")] + public async Task Logout() + { + try { - return await Login(login, true); + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + return Ok(); } - - /// - /// Entfernt das Authentifizierungs-Cookie des Benutzers (AuthCookie) - /// - /// - /// Gibt eine HTTP 200 oder 401. - /// - /// - /// Sample request: - /// - /// POST /api/auth/logout - /// - /// - /// Erfolgreich gelöscht, wenn der Benutzer ein berechtigtes Cookie hat. - /// Wenn es kein zugelassenes Cookie gibt, wird „nicht zugelassen“ zurückgegeben. - [ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")] - [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] - [Authorize] - [HttpPost("logout")] - public async Task Logout() + catch (Exception ex) { - try - { - await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); - return Ok(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Unexpected error occurred.\n{ErrorMessage}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } + _logger.LogError(ex, "Unexpected error occurred.\n{ErrorMessage}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } - - /// - /// Prüft, ob der Benutzer ein autorisiertes Token hat. - /// - /// Wenn ein autorisiertes Token vorhanden ist HTTP 200 asynchron 401 - /// - /// Sample request: - /// - /// GET /api/auth - /// - /// - /// Wenn es einen autorisierten Cookie gibt. - /// Wenn kein Cookie vorhanden ist oder nicht autorisierte. - [ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")] - [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] - [Authorize] - [HttpGet] - public IActionResult IsAuthenticated() => Ok(); } + + /// + /// Prüft, ob der Benutzer ein autorisiertes Token hat. + /// + /// Wenn ein autorisiertes Token vorhanden ist HTTP 200 asynchron 401 + /// + /// Sample request: + /// + /// GET /api/auth + /// + /// + /// Wenn es einen autorisierten Cookie gibt. + /// Wenn kein Cookie vorhanden ist oder nicht autorisierte. + [ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [Authorize] + [HttpGet] + public IActionResult IsAuthenticated() => Ok(); } \ No newline at end of file