Commit 0
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
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 });
|
||||
}
|
||||
|
||||
[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}");
|
||||
}
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user