You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Dotnet-WebAPI/API/Controllers/AuthenticationController.cs

92 lines
2.9 KiB

using System.ComponentModel.DataAnnotations;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using API.Auth;
using API.Validation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Model;
using Services;
namespace API.Controllers;
[ApiController]
public class AuthenticationController(IUserService service, IConfiguration config) : ControllerBase
{
private readonly SymmetricSecurityKey _key = new(Encoding.UTF8.GetBytes(config["JWT:Key"]!));
public record GenerateTokenRequest(
[MaxLength(256, ErrorMessage = "Email address is too wide")]
[EmailAddress]
string Email,
[MaxLength(256, ErrorMessage = "Password is too wide")]
string Password);
private record AuthenticationResponse(String Token, DateTime ExpirationDate);
[HttpPost("/auth/token")]
public async Task<IActionResult> GenerateToken([FromBody] GenerateTokenRequest req)
{
var user = await service.Authorize(req.Email, req.Password);
if (user == null)
return BadRequest(new Dictionary<string, string[]>
{
{ "unauthorized", ["Invalid email or password"] }
});
var (jwt, expirationDate) = GenerateJwt(user);
return Ok(new AuthenticationResponse(jwt, expirationDate));
}
public record RegisterAccountRequest(
[MaxLength(256, ErrorMessage = "name is longer than 256")]
string Username,
[MaxLength(256, ErrorMessage = "email is longer than 256")]
[EmailAddress]
string Email,
[StringLength(256, MinimumLength = 4, ErrorMessage = "password length must be between 4 and 256")]
string Password);
[HttpPost("/auth/register")]
public async Task<IActionResult> RegisterAccount([FromBody] RegisterAccountRequest req)
{
if (await service.GetUser(req.Email) != null)
{
return BadRequest(new Dictionary<string, string[]>
{
{ "email", ["The email address already exists"] }
});
}
var user = await service.CreateUser(
req.Username,
req.Email,
req.Password,
Constants.DefaultProfilePicture,
false
);
var (jwt, expirationDate) = GenerateJwt(user);
return Ok(new AuthenticationResponse(jwt, expirationDate));
}
private (string, DateTime) GenerateJwt(User user)
{
var claims = new List<Claim>
{
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new(JwtRegisteredClaimNames.Sub, user.Email),
new(JwtRegisteredClaimNames.Email, user.Email),
new(IdentityData.IdUserClaimName, user.Id.ToString()),
new(IdentityData.AdminUserClaimName, user.IsAdmin.ToString())
};
return Authentication.GenerateJwt(_key, claims);
}
}