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 // { // 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 { 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, Expiration = token.ValidTo }); 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 { 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) }; var newAccessToken = CreateToken(authClaims); var newRefreshToken = GenerateRefreshToken(); return new ObjectResult(new { Token = new JwtSecurityTokenHandler().WriteToken(newAccessToken), RefreshToken = newRefreshToken, Expiration = newAccessToken.ValidTo }); } private JwtSecurityToken CreateToken(List 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; } } }