using DigitalData.Core.Abstractions.Application; using DigitalData.UserManager.Application.Contracts; using DigitalData.UserManager.Application.DTOs.User; 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; namespace EnvelopeGenerator.GeneratorAPI.Controllers { [Route("api/[controller]")] [ApiController] public class AuthController : ControllerBase { private readonly ILogger _logger; private readonly IUserService _userService; private readonly IDirectorySearchService _dirSearchService; public AuthController(ILogger logger, IUserService userService, IDirectorySearchService dirSearchService) { _logger = logger; _userService = userService; _dirSearchService = dirSearchService; } //TODO: When a user group is created for signFlow, add a process to check if the user is in this group (like "PM_USER") [AllowAnonymous] [HttpPost("login")] public async Task Login([FromBody] LogInDto login) { 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, }; // 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, "Unexpected error occurred.\n{ErrorMessage}", 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, "Unexpected error occurred.\n{ErrorMessage}", ex.Message); return StatusCode(StatusCodes.Status500InternalServerError); } } [AllowAnonymous] [HttpGet("check")] public IActionResult IsAuthenticated() => Ok(User.Identity?.IsAuthenticated ?? false); } }