Library for managing JWT access tokens and refresh tokens using Azure Cosmos DB


Keywords
authentication, azure, cosmosdb, dotnet, jwt, refresh-token
License
Apache-2.0
Install
Install-Package Jwt.Refresh.Token.Cosmos -Version 1.0.1

Documentation

Jwt Refresh Token

.NET library to allowing a client application get new access tokens

Introduction

Jwt Refresh Token is .Net library to provide a importante authentication aspects, and using Jwt Token (learn more jwt.io web site) and Refresh Token.

Refresh Token basically require a unique token identifier to obtain additional access tokens. Access token arent'n valid for an long period for security and Refresh Token strategy can help to re-authentication a user without login credential ๐Ÿค” (some scratches risks here)

Architecture

This project is based in Onion Architecture created by Jeffrey Palermo in 2008.

Flow

Miro

โœ… Supported Databases

The goal of this project is to support the most widely used Azure-compatible databases:

Cosmos DB

To install Jwt.Refresh.Token.Cosmos (include prereleases), run the following command in the .NET CLI

dotnet add package Jwt.Refresh.Token.Cosmos --prerelease
Usage
  1. โœฏ Cosmos setup

The first step to do is provision your cosmos db, or if you already have it, create the token container id (choose name you want) with partitionKey '/userId'.

Implement IUserRepository for get user by id and password. UserId

  1. โœฏ Configure settings app:
{
  "JwtRefreshToken": {
    "Descriptor": {
      "Issuer": "YOUR_ISSUER",
      "Audience": "YOUR_AUDIENCE",
      "AlgorithmKey": "YOUR_ALGORITHM_KEY"
    },
    "Expires": {
     "CreateExpiresInMs": 300000,
  "RefreshExpiresInMs": 604800000
    },
    "Cosmos": {
      "ConnectionString": "YOUR_COSMOS_CONNECTIONSTRING",
      "DatabaseName": "YOUR_DATABASEID",
      "TokenContainerId": "YOUR_TOKEN_CONTAINERID"
    }
  }
}
  1. โœฏ Configure startup and endpoints app:

โš ๏ธ Note: Although this library uses System.Text.Json internally, the Microsoft.Azure.Cosmos SDK still requires Newtonsoft.Json as a runtime dependency. Make sure to install it in your host application to avoid runtime errors:

dotnet add package Newtonsoft.Json 

Now, configure it in your application's Program.cs (startup file):

builder.Services.AddAntiforgery(options =>
{
    // Allow client-side tools (like Swagger or Postman) to access the antiforgery cookie.
    // This is necessary to manually include the cookie in requests for CSRF validation.
    options.Cookie.HttpOnly = false;

    // Set the header name that the antiforgery system expects.
    // This should match what the client sends (e.g., X-XSRF-TOKEN).
    options.HeaderName = "X-XSRF-TOKEN";
});

// Registers the source-generated System.Text.Json context used for serializing tokens and responses.
// This improves performance and avoids runtime errors when reflection-based serialization is disabled.
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain.Add(AppJsonContext.Default);
});

// Register refresh token services
builder.Services.AddJwtRefreshTokenCosmosServices(builder.Configuration, new CosmosClientOptions
{
    ConnectionMode = ConnectionMode.Gateway,
    AllowBulkExecution = true,
    SerializerOptions = new CosmosSerializationOptions
    {
        Indented = true,
        PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase,
        IgnoreNullValues = true
    }
});

// Registers a custom implementation of IUserRepository used to validate credentials and retrieve the userId,
// which is later assigned to the ClaimTypes.NameIdentifier in the generated JWT.
builder.Services.AddScoped<IUserRepository, UserRepository>();

// ๐Ÿ” Secure JWT Authentication Configuration
builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
{
    options.RequireHttpsMetadata = true;
    options.SaveToken = true;

    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(
            Encoding.ASCII.GetBytes(builder.Configuration["JwtRefreshToken:Descriptor:AlgorithmKey"]
                                    ?? throw new InvalidOperationException("JWT key not configured."))
        ),
        ValidateIssuer = true,
        ValidIssuer = builder.Configuration["JwtRefreshToken:Descriptor:Issuer"],
        
        ValidateAudience = true,
        ValidAudience = builder.Configuration["JwtRefreshToken:Descriptor:Audience"],

        ValidateLifetime = true,
        RequireExpirationTime = true,
        ClockSkew = TimeSpan.FromSeconds(30)
    };
});

// Configures the default authorization policy used by the protected endpoints.
// The "Bearer" policy requires a valid JWT token and is associated with the "Bearer" authentication scheme.
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("Bearer", policy =>
    {
        policy.AddAuthenticationSchemes("Bearer");
        policy.RequireAuthenticatedUser();
    });
});

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

// Maps the default refresh token endpoints (POST /token, PATCH /token, PATCH /revoke).
// These endpoints are fully integrated with antiforgery and JWT security mechanisms.
// If needed, you can implement your own custom routes by invoking ITokenAppService directly.
app.MapTokenEndpoints();

app.Run();

See integration test here


๐Ÿงช Sample Project with Postman Support

A complete working example is available in the /sample folder.

It demonstrates:

  • โœ… How to configure and run the minimal API
  • ๐Ÿ” Full antiforgery protection (XSRF)
  • ๐Ÿงช Token creation, refresh, and revocation endpoints
  • ๐Ÿ“ฌ A Postman Collection to test the full flow locally

๐Ÿ“„ See full instructions in /sample/README.md

TODO

  • Incrise unit test coverage
  • Create pipeline
  • Implement Mongo DB infrastructure
  • Implement PostgreeSql infrastructure
  • Implement Sql Databse infrastructure