diff --git a/WorkFlow.API/Controllers/AuthController.cs b/WorkFlow.API/Controllers/AuthController.cs new file mode 100644 index 0000000..cdba3b8 --- /dev/null +++ b/WorkFlow.API/Controllers/AuthController.cs @@ -0,0 +1,154 @@ +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication; +using System.Security.Claims; +using Microsoft.AspNetCore.Mvc; +using DigitalData.UserManager.Application.Contracts; +using DigitalData.UserManager.Application.DTOs.User; +using Microsoft.AspNetCore.Authorization; +using DigitalData.UserManager.Application; +using DigitalData.UserManager.Application.DTOs.Auth; +using DigitalData.Core.Abstractions.Application; +using Microsoft.Extensions.Localization; +using DigitalData.Core.DTO; + +namespace WorkFlow.API.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class AuthController : ControllerBase + { + private readonly IUserService _userService; + private readonly IGroupOfUserService _gouService; + private readonly IDirectorySearchService _dirSearchService; + private readonly IStringLocalizer _localizer; + private readonly ILogger _logger; + + public AuthController(IUserService userService, IGroupOfUserService gouService, IDirectorySearchService directorySearchService, IStringLocalizer localizer, ILogger logger) + { + _userService = userService; + _gouService = gouService; + _dirSearchService = directorySearchService; + _localizer = localizer; + _logger = logger; + } + + [AllowAnonymous] + [HttpGet("check")] + public IActionResult CheckAuthentication() + { + try + { + return Ok(User.Identity?.IsAuthenticated ?? false); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [AllowAnonymous] + [HttpPost("login")] + public async Task Login([FromBody] LogInDto login) + { + try + { + bool isValid = _dirSearchService.ValidateCredentials(login.Username, login.Password); + + if (!isValid) + return Unauthorized(Result.Fail().Message(_localizer[Key.UserNotFound])); + + var gouMsg = await _gouService.HasGroup(login.Username, "PM_USER", caseSensitive: false); + if (!gouMsg.IsSuccess) + return Unauthorized(Result.Fail().Message(_localizer[Key.UnauthorizedUser])); + + //find the user + var uRes = await _userService.ReadByUsernameAsync(login.Username); + if (!uRes.IsSuccess || uRes.Data is null) + { + return Unauthorized(uRes); + } + + 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.UtcNow.AddMinutes(60) + }; + + // Sign in + await HttpContext.SignInAsync( + CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity), + authProperties); + + _dirSearchService.SetSearchRootCache(user.Username, login.Password); + + return Ok(); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [Authorize] + [HttpGet("user")] + public async Task GetUserWithClaims() + { + try + { + // Extract the username from the Name claim. + string? username = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; + + if (string.IsNullOrEmpty(username)) + return Unauthorized(); + + return await _userService.ReadByUsernameAsync(username) + .ThenAsync(Ok, IActionResult (m, n) => + { + _logger.LogNotice(n); + return NotFound(Result.Fail().Message(_localizer[Key.UserNotFound])); + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [Authorize] + [HttpPost("logout")] + public async Task Logout() + { + try + { + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + return Ok(); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + } +} \ No newline at end of file