Files
agologum/api/src/Controllers/AuthController.cs
Blitblank ffdf997929
All checks were successful
Build and Deploy API / build-and-deploy (push) Successful in 9s
add roles to jwt claims
2026-04-21 20:32:48 -05:00

124 lines
4.1 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using agologumApi.Models;
using agologumApi.Services;
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase {
// identity things
private readonly UserManager<User> userManager_;
private readonly SignInManager<User> signInManager_;
private readonly JwtService jwt_;
public AuthController(UserManager<User> userManager, SignInManager<User> signInManager, JwtService jwt) {
userManager_ = userManager;
signInManager_ = signInManager;
jwt_ = jwt;
}
[HttpPost("register")]
public async Task<ActionResult> Register(RegisterDto dto) {
var user = new User {
UserName = dto.UserName,
Email = dto.Email,
CreatedAt = DateTime.UtcNow // yeah why not utc
};
var result = await userManager_.CreateAsync(user, dto.Password);
if(!result.Succeeded) return BadRequest(result.Errors);
// assigning roles to user
string role = "base";
if(dto.UserName == "bard") {
role = "superuser";
} else if(dto.UserName.StartsWith("x")) {
role = "admin";
}
await userManager_.AddToRoleAsync(user, role); // TODO: error check this
// these are here just in case you need them
// await _userManager.RemoveFromRoleAsync(user, "admin"); // remove role
// var roles = await _userManager.GetRolesAsync(user); // get list of roles for user
return CreatedAtAction(
nameof(Register),
new { id = user.Id }
);
}
[HttpPost("login")]
public async Task<ActionResult> Login(LoginDto dto)
{
var user = await userManager_.FindByNameAsync(dto.UserName);
if (user == null) return Unauthorized();
var result = await signInManager_.CheckPasswordSignInAsync(user, dto.Password, false);
if(!result.Succeeded) return Unauthorized();
var accessToken = jwt_.GenerateJwt(user);
var refreshToken = jwt_.GenerateRefreshToken();
RefreshToken newTokenObject = new RefreshToken {
Token = refreshToken,
UserId = user.Id,
CreatedAt = DateTime.UtcNow,
ExpiresAt = DateTime.UtcNow.AddDays(30),
IsRevoked = false
};
await jwt_.AddRefreshToken(newTokenObject);
return Ok(new { accessToken, refreshToken });
}
[Authorize] // authorize is handled by middleware
[HttpPost("logout")]
public async Task<ActionResult> Logout(string refreshTokenString) {
// revoke refresh token
bool success = await jwt_.RevokeRefreshToken(refreshTokenString);
if(!success) return NotFound();
return Ok();
}
[HttpPost("refresh")] // allow-anonymous by default
public async Task<ActionResult> Refresh(TokenDto request) {
RefreshToken? storedToken = await jwt_.GetRefreshToken(request.RefreshToken);
if (storedToken == null) return Unauthorized();
bool valid = (storedToken.IsRevoked) ||
(storedToken.ExpiresAt < DateTime.UtcNow);
if(!valid) return Unauthorized(); // TODO: delete the invalid token
User? user = await jwt_.GetUser(storedToken.UserId);
if(user == null) return NotFound();
string? newAccessToken = await jwt_.GenerateJwt(user);
if(newAccessToken == null) return NotFound();
string newRefreshToken = jwt_.GenerateRefreshToken();
storedToken.IsRevoked = true;
RefreshToken newTokenObject = new RefreshToken {
Token = newRefreshToken,
UserId = storedToken.UserId,
CreatedAt = DateTime.UtcNow,
ExpiresAt = DateTime.UtcNow.AddDays(30),
IsRevoked = false
};
await jwt_.AddRefreshToken(newTokenObject);
return Ok(new { accessToken = newAccessToken, refreshToken = newRefreshToken });
}
// TODO
// email verification
// password reset
// oh hell naw 2FA I do not care enough
}