Skip to main content
net8.0.NETStandard2.1

Token Storage using Azure Blobs

Published
May 19, 2026
5mo ago
Total Downloads
391
391

Install

dotnet add package Alfa1.TokenStorage.Azure.Blobs --version 0.0.1-preview.3
ProductVersions
.NET
net8.0
.NET Standard
netstandard2.1

README

Alfa1.TokenStorage - Registration Guide

This package family supports multiple storage providers for ITokenStorageService.

Registration styles

All providers support these patterns:

  1. Default registration (single ITokenStorageService)
  2. Keyed registration (multiple named token stores)
  3. Consumer-bound registration (bind a dependent type to one token identifier)

SQL Server

// Default registration (single ITokenStorageService)
services.AddTokenStorageSqlServer(configuration);

// Keyed registrations (multiple named token stores)
services.AddKeyedTokenStorageSqlServer("TypeA", "TypeAToken", configuration);
services.AddKeyedTokenStorageSqlServer("TypeB", "TypeBToken", configuration);

// Individual registrations (bind token store per dependent type)
services.AddTokenStorageSqlServerFor<TypeA>(configuration, "TypeAToken");
services.AddTokenStorageSqlServerFor<TypeB>(configuration); // defaults to "TypeB"

appsettings.json for SQL Server:

{
  "ConnectionStrings": {
    "Tokens": "Server=.;Database=TokenDb;Trusted_Connection=True;TrustServerCertificate=True"
  },
  "SqlServerTokenStorageOptions": {
    "ConnectionStringName": "Tokens",
    "TableName": "Tokens",
    "TokenIdentifierColumnName": "TokenIdentifier",
    "TokenIdentifier": "default",
    "RefreshTokenColumnName": "RefreshToken",
    "RefreshTokenUpdatedAtColumnName": "RefreshTokenUpdatedAt",
    "AccessTokenColumnName": "AccessToken",
    "AccessTokenUpdatedAtColumnName": "AccessTokenUpdatedAt",
    "AccessTokenExpireColumnName": "AccessTokenExpireAt"
  }
}

PostgreSQL

// Default registration (single ITokenStorageService)
services.AddAuthenticationTokenStoragePostgreSQL(configuration);

// Keyed registrations (multiple named token stores)
services.AddKeyedAuthenticationTokenStoragePostgreSQL("TypeA", "TypeAToken", configuration);
services.AddKeyedAuthenticationTokenStoragePostgreSQL("TypeB", "TypeBToken", configuration);

// Individual registrations (bind token store per dependent type)
services.AddAuthenticationTokenStoragePostgreSQLFor<TypeA>(configuration, "TypeAToken");
services.AddAuthenticationTokenStoragePostgreSQLFor<TypeB>(configuration); // defaults to "TypeB"

appsettings.json for PostgreSQL:

{
  "ConnectionStrings": {
    "Tokens": "Host=localhost;Port=5432;Database=token_db;Username=postgres;Password=postgres"
  },
  "PostgreSQLTokenStorageOptions": {
    "ConnectionStringName": "Tokens",
    "TableName": "Tokens",
    "TokenIdentifierColumnName": "TokenIdentifier",
    "TokenIdentifier": "default",
    "RefreshTokenColumnName": "RefreshToken",
    "RefreshTokenUpdatedAtColumnName": "RefreshTokenUpdatedAt",
    "AccessTokenColumnName": "AccessToken",
    "AccessTokenUpdatedAtColumnName": "AccessTokenUpdatedAt",
    "AccessTokenExpireColumnName": "AccessTokenExpireAt"
  }
}

File system

// Default registration (single ITokenStorageService)
services.AddTokenStorageFileSystem(configuration);

// Keyed registrations (multiple named token stores)
services.AddKeyedTokenStorageFileSystem("TypeA", "TypeAToken", configuration);
services.AddKeyedTokenStorageFileSystem("TypeB", "TypeBToken", configuration);

// Individual registrations (bind token store per dependent type)
services.AddTokenStorageFileSystemFor<TypeA>(configuration, "TypeAToken");
services.AddTokenStorageFileSystemFor<TypeB>(configuration); // defaults to "TypeB"

appsettings.json for File system:

{
  "FileSystemTokenStorageOptions": {
    "TokenIdentifier": "default",
    "RefreshTokenFilePathTemplate": "tokens/refresh.{tokenIdentifier}.txt",
    "AccessTokenFilePathTemplate": "tokens/access.{tokenIdentifier}.txt"
  }
}

FileSystemTokenStorageOptions supports template paths using {tokenIdentifier}:

{
  "FileSystemTokenStorageOptions": {
    "RefreshTokenFilePathTemplate": "tokens/refresh.{tokenIdentifier}.txt",
    "AccessTokenFilePathTemplate": "tokens/access.{tokenIdentifier}.txt"
  }
}

For TypeAToken this resolves to tokens/refresh.TypeAToken.txt and tokens/access.TypeAToken.txt.

Azure Blobs

// Default registration (single ITokenStorageService)
services.AddTokenStorageAzureBlobs(configuration);

// Keyed registrations (multiple named token stores)
services.AddKeyedTokenStorageAzureBlobs("TypeA", "TypeAToken", configuration);
services.AddKeyedTokenStorageAzureBlobs("TypeB", "TypeBToken", configuration);

// Individual registrations (bind token store per dependent type)
services.AddTokenStorageAzureBlobsFor<TypeA>(configuration, "TypeAToken");
services.AddTokenStorageAzureBlobsFor<TypeB>(configuration); // defaults to "TypeB"

appsettings.json for Azure Blobs:

{
  "AzureBlobsTokenStorageOptions": {
    "ConnectionString": "<azure-storage-connection-string>",
    "ContainerName": "tokens",
    "TokenIdentifier": "default",
    "RefreshTokenFilePathTemplate": "refresh.{tokenIdentifier}.txt",
    "AccessTokenFilePathTemplate": "access.{tokenIdentifier}.txt"
  }
}

AzureBlobsTokenStorageOptions supports template blob paths using {tokenIdentifier}:

{
  "AzureBlobsTokenStorageOptions": {
    "RefreshTokenFilePathTemplate": "refresh.{tokenIdentifier}.txt",
    "AccessTokenFilePathTemplate": "access.{tokenIdentifier}.txt"
  }
}

For TypeAToken this resolves to refresh.TypeAToken.txt and access.TypeAToken.txt.


Mix and match providers

You can register different providers side-by-side using keyed services:

services.AddKeyedTokenStorageSqlServer("ApiA", "ApiAToken", configuration);
services.AddKeyedTokenStorageAzureBlobs("ApiB", "ApiBToken", configuration);

Then resolve by key where needed:

var tokenStorageA = serviceProvider.GetRequiredKeyedService<ITokenStorageService>("ApiA");
var tokenStorageB = serviceProvider.GetRequiredKeyedService<ITokenStorageService>("ApiB");

Notes

  • ITokenStorageService remains unchanged.
  • Token scoping is controlled internally by tokenIdentifier.
  • If you omit tokenIdentifier in ...For<T>(), the default is the dependent type name.

Adoption Assessment

Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.

This version is marked prerelease. Validate its API and upgrade path before production use.Compatibility metadata lists 2 target frameworks; confirm the exact target used by your application.The published metadata declares 16 direct dependency entries across framework groups. Inspect the resolved dependency graph for your target framework.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.