Files
auth-mistox/src/Server/Controllers/MAuth.cs
T
derek 0bdc90f054
Docker Build and Release Upload / build (push) Has been cancelled
Fix login issue when on same site
2025-09-09 21:58:08 -07:00

128 lines
5.7 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Auth.Services.DatabaseService;
using System.Web.Http;
using Auth.Entities;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Auth.Services;
using Auth.DTO;
using System.Security.Cryptography;
using System.Text;
namespace Auth.Controllers {
[ApiController]
[Route("api/auth/")]
public class MAuthController : MistoxControllerBase {
public MAuthController(DatabaseService db) : base(db) { }
// Sends the public key to clients so they can verify sessions. - Verified working
[HttpGet("publickey")]
public IActionResult PublicKey() {
try {
RSA rsa = AuthJWT.RsaPublicKey.Rsa;
byte[] publicKey = rsa.ExportSubjectPublicKeyInfo();
string base64 = Convert.ToBase64String(publicKey);
StringBuilder sb = new StringBuilder();
sb.AppendLine("-----BEGIN PUBLIC KEY-----");
for (int i = 0; i < base64.Length; i += 64) {
sb.AppendLine(base64.Substring(i, Math.Min(64, base64.Length - i)));
}
sb.AppendLine("-----END PUBLIC KEY-----");
return Ok(sb.ToString());
} catch (SecurityTokenException ex) {
return BadRequest("Token invalid: " + ex.Message);
}
}
// Login and return a ticket to retreive your JWT - Verified working
[HttpPost("login")]
public async Task<ActionResult> Authenticate([FromBody] LoginRequest request) {
try {
Account? test = await _databaseService.GetAccount(request.UserName.ToLower());
if (test != null) {
if (test.EmailVerified == true) {
if (test.FailedPasswordLock) {
if (test.CurrentPasswordAttempts >= test.PasswordAttempts) {
return BadRequest("Too many failed password attempts. Please reset your password");
}
}
if (BCrypt.Net.BCrypt.Verify(request.Password, test.PasswordHash)) {
test.CurrentPasswordAttempts = 0;
await _databaseService.SetAccount(test);
if (request.Site == "/") {
SignIn(Response, AuthJWT.GenereateJWTToken(test, request.Site, request.StayLoggedIn));
return Ok();
} else {
string Ticket = Guid.NewGuid().ToString().Replace("-", "");
string JWT = AuthJWT.GenereateJWTToken(test, request.Site, request.StayLoggedIn);
AuthJWT.LoginSessions[Ticket] = new JWTMemCache {
JWT = JWT,
ExpiresAt = DateTime.UtcNow.AddSeconds(20)
};
return Ok(Ticket);
}
} else {
test.CurrentPasswordAttempts += 1;
await _databaseService.SetAccount(test);
return BadRequest("Wrong Password");
}
} else {
return BadRequest("You need to verify your email before you can sign in");
}
}
return BadRequest("Account Not Found");
} catch (Exception ex) {
Console.WriteLine("Login Error: " + ex.Message);
return BadRequest("An internal server error has occured");
}
}
// Use your ticket to get the JWT - Verified working
[HttpPost("token")]
public ActionResult Token([FromBody] JWTRequest request) {
try {
if (AuthJWT.LoginSessions.ContainsKey(request.Ticket)) {
JWTMemCache JWTObj = AuthJWT.LoginSessions[request.Ticket];
if (JWTObj.ExpiresAt >= DateTime.UtcNow) {
string JWT = JWTObj.JWT;
AuthJWT.LoginSessions.Remove(request.Ticket);
return Ok(JWT);
} else {
AuthJWT.LoginSessions.Remove(request.Ticket);
return BadRequest("The session ticket has already expired");
}
}
return BadRequest("The session ticket cannot be found");
} catch (Exception ex) {
Console.WriteLine("Token Error: " + ex.Message);
return BadRequest("An internal server error has occured");
}
}
// Renews an old JWT before it expires - Not Tested
[HttpPost("renew")]
public IActionResult Session([FromBody] JWTRenewRequest request) {
try {
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
ClaimsPrincipal claimsPrincipal = handler.ValidateToken(request.JWT, AuthJWT.TokenParameters, out var validatedToken);
JwtSecurityToken jwt = (JwtSecurityToken)validatedToken;
if (jwt != null) {
if (jwt.ValidTo - DateTime.UtcNow < TimeSpan.FromDays(1)) {
var newJwt = AuthJWT.RenewJWTToken(claimsPrincipal);
return Ok(newJwt);
}
return BadRequest("Not ready to renew");
}
return BadRequest("Malformed Token");
} catch (SecurityTokenException ex) {
return BadRequest("Token invalid: " + ex.Message);
}
}
}
}