Generating and Refreshing JWT Token in ASP.NET API

Generating and Refreshing JWT Token in ASP.NET API (Advanced)
In this advanced guide, we will implement a production-ready JWT authentication system in ASP.NET API with Refresh Tokens, database validation, and proper security practices.
Create User Table
We will store users along with refresh tokens and expiry. This allows secure token regeneration without re-login.
CREATE TABLE Users(
    UserId INT IDENTITY PRIMARY KEY,
    Username VARCHAR(100),
    PasswordHash VARCHAR(500),
    RefreshToken VARCHAR(500),
    RefreshTokenExpiryTime DATETIME
)
Install Required Packages
  • Microsoft.AspNetCore.Authentication.JwtBearer
  • System.IdentityModel.Tokens.Jwt
  • Microsoft.EntityFrameworkCore.SqlServer
Create Models
Models define database structure and API responses.
public class UserModel
{
    public int UserId { get; set; }
    public string Username { get; set; }
    public string PasswordHash { get; set; }
    public string RefreshToken { get; set; }
    public DateTime RefreshTokenExpiryTime { get; set; }
}

public class LoginModel
{
    public string Username { get; set; }
    public string Password { get; set; }
}

public class TokenResponse
{
    public string AccessToken { get; set; }
    public string RefreshToken { get; set; }
}
DbContext Class
Entity Framework DbContext is used to communicate with SQL Server database.
using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {
    }

    public DbSet<UserModel> Users { get; set; }
}
JWT Service
This service generates JWT tokens and refresh tokens securely.
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

public class JwtService
{
    private readonly string secretKey = "SUPER_SECRET_KEY_12345";

    public string GenerateAccessToken(string username)
    {
        SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));

        SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        List<Claim> claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, username)
        };

        JwtSecurityToken token = new JwtSecurityToken(
            claims: claims,
            expires: DateTime.UtcNow.AddMinutes(5),
            signingCredentials: credentials
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    public string GenerateRefreshToken()
    {
        return Guid.NewGuid().ToString();
    }
}
Auth Controller
Controller handles login and refresh logic using database validation.
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
    private readonly AppDbContext _context;
    private readonly JwtService _jwtService;

    public AuthController(AppDbContext context)
    {
        _context = context;
        _jwtService = new JwtService();
    }

    [HttpPost("login")]
    public IActionResult Login(LoginModel model)
    {
        UserModel user = _context.Users
            .FirstOrDefault(u => u.Username == model.Username && u.PasswordHash == model.Password);

        if (user == null)
        {
            return Unauthorized();
        }

        string accessToken = _jwtService.GenerateAccessToken(user.Username);
        string refreshToken = _jwtService.GenerateRefreshToken();

        user.RefreshToken = refreshToken;
        user.RefreshTokenExpiryTime = DateTime.UtcNow.AddDays(7);

        _context.SaveChanges();

        TokenResponse response = new TokenResponse
        {
            AccessToken = accessToken,
            RefreshToken = refreshToken
        };

        return Ok(response);
    }

    [HttpPost("refresh")]
    public IActionResult Refresh(TokenResponse token)
    {
        UserModel user = _context.Users
            .FirstOrDefault(u => u.RefreshToken == token.RefreshToken);

        if (user == null || user.RefreshTokenExpiryTime < DateTime.UtcNow)
        {
            return Unauthorized();
        }

        string newAccessToken = _jwtService.GenerateAccessToken(user.Username);
        string newRefreshToken = _jwtService.GenerateRefreshToken();

        user.RefreshToken = newRefreshToken;
        user.RefreshTokenExpiryTime = DateTime.UtcNow.AddDays(7);

        _context.SaveChanges();

        return Ok(new TokenResponse
        {
            AccessToken = newAccessToken,
            RefreshToken = newRefreshToken
        });
    }
}
Configure JWT in Program.cs
This step enables JWT authentication middleware in ASP.NET Core.
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience = false,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(
            Encoding.UTF8.GetBytes("SUPER_SECRET_KEY_12345"))
    };
});

app.UseAuthentication();
app.UseAuthorization();
Request & Response
POST /api/auth/login

{
  "username": "admin",
  "password": "123"
}
Response:

{
  "accessToken": "JWT_TOKEN",
  "refreshToken": "REFRESH_TOKEN"
}
Now your API is fully secured using JWT with refresh tokens and database validation. You can protect endpoints using [Authorize].

Post a Comment