148 lines
4.8 KiB
C#
148 lines
4.8 KiB
C#
using GameAuthApi.Models;
|
|
using GameAuthApi.Services;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using System;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Linq;
|
|
using System.Security.Claims;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace GameAuthApi.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class AuthController : ControllerBase
|
|
{
|
|
private readonly UserService _userService;
|
|
private readonly IConfiguration _config;
|
|
private readonly BlacklistService _blacklistService;
|
|
|
|
public AuthController(UserService userService, IConfiguration config, BlacklistService blacklistService)
|
|
{
|
|
_userService = userService;
|
|
_config = config;
|
|
_blacklistService = blacklistService;
|
|
}
|
|
|
|
[HttpPost("register")]
|
|
public async Task<IActionResult> Register([FromBody] RegisterRequest credentials)
|
|
{
|
|
if (await _userService.GetByUsernameAsync(credentials.Username) != null)
|
|
return BadRequest("User already exists");
|
|
|
|
var hash = BCrypt.Net.BCrypt.HashPassword(credentials.Password);
|
|
|
|
var user = new User
|
|
{
|
|
Username = credentials.Username,
|
|
PasswordHash = hash,
|
|
Role = "USER",
|
|
Email = credentials.Email
|
|
};
|
|
|
|
await _userService.CreateAsync(user);
|
|
return Ok("User created");
|
|
}
|
|
|
|
[HttpPost("login")]
|
|
public async Task<IActionResult> Login([FromBody] LoginRequest credentials)
|
|
{
|
|
var user = await _userService.GetByUsernameAsync(credentials.Username);
|
|
if (user == null || !BCrypt.Net.BCrypt.Verify(credentials.Password, user.PasswordHash))
|
|
return Unauthorized();
|
|
|
|
var accessToken = GenerateJwtToken(user);
|
|
var refreshToken = Guid.NewGuid().ToString();
|
|
var refreshExpiry = DateTime.UtcNow.AddDays(7);
|
|
|
|
user.RefreshToken = refreshToken;
|
|
user.RefreshTokenExpiry = refreshExpiry;
|
|
await _userService.UpdateAsync(user);
|
|
|
|
return Ok(new { accessToken, refreshToken, user.Role });
|
|
}
|
|
|
|
[HttpPost("refresh")]
|
|
public async Task<IActionResult> Refresh([FromBody] RefreshRequest req)
|
|
{
|
|
var user = await _userService.GetByUsernameAsync(req.Username);
|
|
if (user == null || user.RefreshToken != req.RefreshToken || user.RefreshTokenExpiry < DateTime.UtcNow)
|
|
return Unauthorized("Invalid or expired refresh token");
|
|
|
|
var newAccessToken = GenerateJwtToken(user);
|
|
return Ok(new { accessToken = newAccessToken });
|
|
}
|
|
|
|
[HttpPost("logout")]
|
|
[Authorize(Roles = "USER,SUPER")]
|
|
public async Task<IActionResult> Logout()
|
|
{
|
|
var token = HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Replace("Bearer ", "");
|
|
if (string.IsNullOrWhiteSpace(token))
|
|
return BadRequest("Token missing");
|
|
|
|
var jwtToken = new JwtSecurityTokenHandler().ReadToken(token) as JwtSecurityToken;
|
|
var expiry = jwtToken.ValidTo;
|
|
|
|
await _blacklistService.AddToBlacklistAsync(token, expiry);
|
|
return Ok("Token blacklisted, user logged out.");
|
|
}
|
|
|
|
[HttpPost("role")]
|
|
[Authorize(Roles = "SUPER")]
|
|
public async Task<IActionResult> ChangeUserRole([FromBody] ChangeRoleRequest request)
|
|
{
|
|
if (request.NewRole != "USER" && request.NewRole != "SUPER")
|
|
return BadRequest("Role must be 'USER' or 'SUPER'");
|
|
|
|
var user = await _userService.GetByUsernameAsync(request.Username);
|
|
if (user == null)
|
|
return NotFound("User not found");
|
|
|
|
user.Role = request.NewRole;
|
|
await _userService.UpdateAsync(user);
|
|
|
|
return Ok($"{request.Username}'s role updated to {request.NewRole}");
|
|
}
|
|
|
|
[HttpGet("users")]
|
|
[Authorize(Roles = "SUPER")]
|
|
public async Task<IActionResult> GetAllUsers()
|
|
{
|
|
var users = await _userService.GetAllAsync();
|
|
return Ok(users);
|
|
}
|
|
|
|
|
|
private string GenerateJwtToken(User user)
|
|
{
|
|
var key = Encoding.UTF8.GetBytes(_config["Jwt:Key"]);
|
|
var creds = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256);
|
|
|
|
var claims = new[]
|
|
{
|
|
new Claim(ClaimTypes.Name, user.Username),
|
|
new Claim(ClaimTypes.NameIdentifier, user.Id),
|
|
new Claim(ClaimTypes.Role, user.Role)
|
|
};
|
|
|
|
var token = new JwtSecurityToken(
|
|
_config["Jwt:Issuer"],
|
|
_config["Jwt:Issuer"],
|
|
claims,
|
|
expires: DateTime.UtcNow.AddMinutes(15),
|
|
signingCredentials: creds);
|
|
|
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
|
}
|
|
|
|
public class RefreshRequest
|
|
{
|
|
public string Username { get; set; }
|
|
public string RefreshToken { get; set; }
|
|
}
|
|
} |