using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using T120B165_ImgBoard.Data; using T120B165_ImgBoard.Models; namespace T120B165_ImgBoard.Services; public interface ITokenService { Task GenerateJwtToken(User user); Task GenerateRefreshToken(User user); Task GetRefreshTokenByValue(string refreshToken); Task InvalidateRefreshToken(RefreshToken refreshToken); } public class TokenService(ImgBoardContext context, IConfiguration config, UserManager userManager): ITokenService { // TODO: replace refresh with JWT token public async Task GetRefreshTokenByValue(string refreshToken) { return await context.RefreshTokens.Where(t => t.Token == refreshToken && t.Expires > DateTime.Now) .Include(t => t.User) .FirstOrDefaultAsync(); } public async Task InvalidateRefreshToken(RefreshToken refreshToken) { context.RefreshTokens.Remove(refreshToken); await context.SaveChangesAsync(); return true; } public async Task GenerateJwtToken(User user) { return await GenerateJwtToken( user, DateTime.Now.AddMinutes(Convert.ToDouble(config["Jwt:DurationInMinutes"])) ); } private async Task GenerateJwtToken(User user, DateTime dateExpire) { var roles = await userManager.GetRolesAsync(user); var claims = new List { new(JwtRegisteredClaimNames.Sub, user.Id), new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new(JwtRegisteredClaimNames.Email, user.Email) }; claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role))); var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: config["Jwt:Issuer"], audience: config["Jwt:Audience"], claims: claims, expires: dateExpire, signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } public async Task GenerateRefreshToken(User user) { var dateExpire = DateTime.Now.AddDays(30); var jwtToken = await GenerateJwtToken(user, dateExpire); var token = new RefreshToken { Expires = dateExpire, Token = jwtToken, User = user }; await context.RefreshTokens.AddAsync(token); await context.SaveChangesAsync(); return token.Token; } }