125 lines
4.4 KiB
C#
125 lines
4.4 KiB
C#
using Asp.Versioning;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Options;
|
|
using Mirea.Api.Dto.Common;
|
|
using Mirea.Api.Dto.Requests;
|
|
using Mirea.Api.Endpoint.Common.Attributes;
|
|
using Mirea.Api.Endpoint.Common.Exceptions;
|
|
using Mirea.Api.Endpoint.Common.MapperDto;
|
|
using Mirea.Api.Endpoint.Common.Services;
|
|
using Mirea.Api.Endpoint.Configuration.Model;
|
|
using Mirea.Api.Security.Common.Domain;
|
|
using Mirea.Api.Security.Services;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Mirea.Api.Endpoint.Controllers.V1;
|
|
|
|
[ApiVersion("1.0")]
|
|
public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, PasswordHashService passwordService) : BaseController
|
|
{
|
|
private CookieOptionsParameters GetCookieParams() =>
|
|
new()
|
|
{
|
|
Domain = HttpContext.GetCurrentDomain(),
|
|
Path = UrlHelper.GetSubPathWithoutFirstApiName + "api"
|
|
};
|
|
|
|
[HttpPost("Login")]
|
|
[BadRequestResponse]
|
|
public async Task<ActionResult<TwoFactorAuthentication>> Login([FromBody] LoginRequest request)
|
|
{
|
|
var userEntity = user.Value;
|
|
|
|
if (!userEntity.Username.Equals(request.Username, StringComparison.OrdinalIgnoreCase) &&
|
|
!userEntity.Email.Equals(request.Username, StringComparison.OrdinalIgnoreCase))
|
|
return BadRequest("Invalid username/email or password");
|
|
|
|
var tokenResult = await auth.LoginAsync(
|
|
GetCookieParams(),
|
|
new User
|
|
{
|
|
Id = 1.ToString(),
|
|
Username = userEntity.Username,
|
|
Email = userEntity.Email,
|
|
PasswordHash = userEntity.PasswordHash,
|
|
Salt = userEntity.Salt,
|
|
TwoFactorAuthenticator = userEntity.TwoFactorAuthenticator,
|
|
SecondFactorToken = userEntity.Secret
|
|
},
|
|
HttpContext, request.Password);
|
|
|
|
return Ok(tokenResult.ConvertToDto());
|
|
}
|
|
|
|
[HttpPost("2FA")]
|
|
[BadRequestResponse]
|
|
public async Task<ActionResult<bool>> TwoFactorAuth([FromBody] TwoFactorAuthRequest request)
|
|
{
|
|
var tokenResult = await auth.LoginAsync(GetCookieParams(), HttpContext, request.Method.ConvertFromDto(), request.Code);
|
|
return Ok(tokenResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Refreshes the authentication token using the existing refresh token.
|
|
/// </summary>
|
|
/// <returns>User's AuthRoles.</returns>
|
|
[HttpGet("ReLogin")]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
|
public async Task<ActionResult<AuthRoles>> ReLogin()
|
|
{
|
|
await auth.RefreshTokenAsync(GetCookieParams(), HttpContext);
|
|
return Ok(AuthRoles.Admin);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Logs the user out by clearing the refresh token and performing any necessary cleanup.
|
|
/// </summary>
|
|
/// <returns>An Ok response if the logout was successful.</returns>
|
|
[HttpGet("Logout")]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
[Authorize]
|
|
public async Task<ActionResult> Logout()
|
|
{
|
|
await auth.LogoutAsync(GetCookieParams(), HttpContext);
|
|
return Ok();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the role of the authenticated user.
|
|
/// </summary>
|
|
/// <returns>The role of the authenticated user.</returns>
|
|
[HttpGet("GetRole")]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
[Authorize]
|
|
public ActionResult<AuthRoles> GetRole() => Ok(AuthRoles.Admin);
|
|
|
|
[HttpPost("RenewPassword")]
|
|
[ApiExplorerSettings(IgnoreApi = true)]
|
|
[Localhost]
|
|
[BadRequestResponse]
|
|
public ActionResult<string> RenewPassword([FromBody] string? password = null)
|
|
{
|
|
if (string.IsNullOrEmpty(password))
|
|
password = string.Empty;
|
|
else if (!PasswordHashService.HasPasswordInPolicySecurity(password))
|
|
throw new ControllerArgumentException("The password must be at least 8 characters long and contain at least one uppercase letter and one special character.");
|
|
|
|
while (!PasswordHashService.HasPasswordInPolicySecurity(password))
|
|
password = GeneratorKey.GenerateAlphaNumeric(16, includes: "!@#%^");
|
|
|
|
var (salt, hash) = passwordService.HashPassword(password);
|
|
|
|
var admin = user.Value;
|
|
|
|
admin.Salt = salt;
|
|
admin.PasswordHash = hash;
|
|
admin.SaveSetting();
|
|
|
|
return Ok(password);
|
|
}
|
|
}
|