175 lines
6.9 KiB
C#
175 lines
6.9 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,
|
|
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<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)
|
|
};
|
|
|
|
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<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;
|
|
}
|
|
}
|
|
|
|
}
|