OBSBoards/OBSBoardsApi/Controllers/AuthenticateController.cs
2024-11-03 17:32:03 +01:00

174 lines
6.8 KiB
C#

using OBSBoardsApi.Model;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Swashbuckle.AspNetCore.Annotations;
using System.Data;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
namespace OBSBoardsApi.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class AuthenticateController : ControllerBase
{
private readonly IConfiguration _configuration;
public AuthenticateController(IConfiguration configuration)
{
_configuration = configuration;
}
private string GetIpAddressOfClient()
{
string ipAddress = string.Empty;
IPAddress ip = Request.HttpContext.Connection.RemoteIpAddress;
if (ip!=null)
{
if (ip.AddressFamily == AddressFamily.InterNetworkV6)
{
try
{
ip = Dns.GetHostEntry(ip).AddressList.First(x => x.AddressFamily == AddressFamily.InterNetwork);
} catch (Exception e)
{
}
finally
{
}
}
ipAddress = ip.ToString();
}
return ipAddress;
}
[HttpPost]
[SwaggerResponse(200, "Token, RefreshToken, Expiration, Roles")]
public IActionResult Login([FromBody]UserModel login)
{
//using (var context = new EpioneContext(_configuration))
//{
// var sha1 = System.Security.Cryptography.SHA1.Create();
// var p = sha1.ComputeHash(Encoding.UTF8.GetBytes(login.Password));
// var pwd = BitConverter.ToString(p).Replace("-", "").ToLower();
// var loggedUser = context.Users.Where(u => u.Name == login.Username && u.Password == pwd).FirstOrDefault();
// if (loggedUser!=null)
// {
// var authClaims = new List<Claim>
// {
// new Claim(ClaimTypes.Name, login.Username),
// new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
// new Claim("Id", loggedUser.Id.ToString()),
// new Claim(ClaimTypes.Role, "User")
// };
// var token = CreateToken(authClaims);
// var refreshToken = GenerateRefreshToken();
// context.Logs.Add(new Log { CreateDateTime = DateTime.Now, Method = MethodBase.GetCurrentMethod().Name, Value = "UserId: "+loggedUser.Id+"; IP: " + GetIpAddressOfClient() });
// context.SaveChanges();
// return Ok(new
// {
// Token = new JwtSecurityTokenHandler().WriteToken(token),
// RefreshToken = refreshToken,
// Expiration = token.ValidTo
// });
// }
//}
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, login.Username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("Id", "test"),
new Claim(ClaimTypes.Role, "User")
};
var token = CreateToken(authClaims);
var refreshToken = GenerateRefreshToken();
return Ok(new
{
Token = new JwtSecurityTokenHandler().WriteToken(token),
RefreshToken = refreshToken
});
return Unauthorized();
}
[HttpPost]
public IActionResult RefreshToken([FromBody]TokenModel tokenModel)
{
if (string.IsNullOrEmpty(tokenModel.Token) || string.IsNullOrEmpty(tokenModel.RefreshToken))
{
return BadRequest("Invalid client request");
}
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, GetPrincipalFromExpiredToken(tokenModel.Token).Identity.Name),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("Id", GetPrincipalFromExpiredToken(tokenModel.Token).Claims.Where(c=>c.Type=="Id").FirstOrDefault().Value),
new Claim(ClaimTypes.Role, "User")
};
var newAccessToken = CreateToken(authClaims);
var newRefreshToken = GenerateRefreshToken();
return new ObjectResult(new
{
Token = new JwtSecurityTokenHandler().WriteToken(newAccessToken),
RefreshToken = newRefreshToken
});
}
private JwtSecurityToken CreateToken(List<Claim> authClaims)
{
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Key"]));
_ = int.TryParse(_configuration["JWT:TokenValidityInMinutes"], out int tokenValidityInMinutes);
var token = new JwtSecurityToken(
issuer: _configuration["JWT:Issuer"],
audience: _configuration["JWT:Audience"],
expires: DateTime.Now.AddMinutes(tokenValidityInMinutes),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return token;
}
private static string GenerateRefreshToken()
{
var randomNumber = new byte[64];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
private ClaimsPrincipal? GetPrincipalFromExpiredToken(string? token)
{
var tokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Key"])),
ValidateLifetime = false
};
var tokenHandler = new JwtSecurityTokenHandler();
var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out SecurityToken securityToken);
if (securityToken is not JwtSecurityToken jwtSecurityToken || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
throw new SecurityTokenException("Invalid token");
return principal;
}
}
}