Because I would be deploying my RAG application along with my website, I decided to secure my embedding and chat endpoints. Yes, it is selfish but I am writing all these first for myself :).

To keep things simple and local, I chose to use JWT tokens for authentication. My approach uses in-memory token generation and validation—no external dependencies or persistent storage required. This is a solid starting point, and you can always enhance it later as your needs grow.


Why Secure Your RAG Endpoints?

When deploying a Retrieval-Augmented Generation (RAG) application alongside a website, securing endpoints is crucial to prevent unauthorized access and protect your data and compute resources. Simplicity and local security are my priorities, so I chose JWT (JSON Web Token) authentication to protect my embedding and chat endpoints.

This approach ensures secure token-based authentication without external dependencies or persistent storage. It’s a solid foundation that can be easily extended as your needs evolve.


What is a JWT Token?

A JSON Web Token (JWT) is a compact, self-contained way to securely transmit information between parties as a JSON object. JWTs are widely used for authentication and authorization in modern web applications.

JWT Structure

A JWT consists of three parts, separated by dots (.):

  1. Header – Contains metadata, including the signing algorithm.
  2. Payload – Holds claims (user information or other data).
  3. Signature – Ensures the integrity and authenticity of the token.

Why Use JWTs?

  • 🔐 Security – JWTs are digitally signed, preventing tampering without session storage.
  • 🚀 Efficiency – Stateless authentication means fewer database checks and faster requests.
  • Authorization – Authenticated users include their JWT in requests for access.

My Approach: Local-Only JWT Authentication

  • No External Dependencies – All token generation and validation occur in-memory.
  • Lightweight & Simple – Easy to integrate into ASP.NET Core minimal API projects.
  • Scalable & Extendable – Future enhancements could include refresh tokens or identity provider integrations.

Implementation: Configuring JWT in ASP.NET Core

To secure API endpoints, first configure JWT authentication in Program.cs:

var jwtSettings = builder.Configuration.GetSection("Jwt");
var key = Encoding.UTF8.GetBytes(jwtSettings["Key"]);

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = jwtSettings["Issuer"],
        ValidAudience = jwtSettings["Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(key)
    };
});

Key Enhancements:
✔ Validate issuer and audience for extra security
✔ Ensure tokens expire (ValidateLifetime)
✔ Use a symmetric key for signing tokens


Generating JWT Tokens in ASP.NET Core

The /token endpoint issues JWTs based on simple local authentication:

app.MapPost("/token", ([FromBody] UserLogin login) =>
{
    if (login.Username == "admin" && login.Password == "password") // Replace with real validation
    {
        var jwtSettings = app.Configuration.GetSection("Jwt");
        var key = Encoding.UTF8.GetBytes(jwtSettings["Key"]);
        var tokenHandler = new JwtSecurityTokenHandler();

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, login.Username) }),
            Expires = DateTime.UtcNow.AddMinutes(int.Parse(jwtSettings["ExpiresMinutes"])),
            Issuer = jwtSettings["Issuer"],
            Audience = jwtSettings["Audience"],
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };

        var token = tokenHandler.CreateToken(tokenDescriptor);
        return Results.Ok(new { token = tokenHandler.WriteToken(token) });
    }

    return Results.Unauthorized();
});

public record UserLogin(string Username, string Password);

Recommended Improvements:
✔ Replace hardcoded credentials with database validation
✔ Introduce role-based access control (ClaimTypes.Role)
✔ Add refresh tokens for long-term authentication


Next Steps

Now that we have JWT authentication configured, the next step is to secure your API endpoints by requiring valid JWTs. You can further enhance your security by adding role-based access, token expiration handling, and integrating with external identity providers as your application grows.


Summary:
JWT authentication is a simple, effective way to secure your local RAG endpoints in ASP.NET Core. Start with in-memory validation for local projects, and extend as your needs evolve.

Related Posts