Installation

Pull and run the pre-built image:

docker run -p 8080:8080 \
  -e Storage__ConnectionString="your-connection-string" \
  -e Issuer="https://auth.example.com" \
  drawboardci/authagonal

Docker Compose

For local development with Azurite (Azure Storage emulator):

services:
  azurite:
    image: mcr.microsoft.com/azure-storage/azurite
    ports:
      - "10000:10000"
      - "10001:10001"
      - "10002:10002"

  authagonal:
    build: .
    ports:
      - "8080:8080"
    environment:
      - Storage__ConnectionString=DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;TableEndpoint=http://azurite:10002/devstoreaccount1;
      - Issuer=http://localhost:8080
    depends_on:
      - azurite
docker compose up

Building from Source

Prerequisites

Build

# Build everything
dotnet build

# Build the login SPA
cd login-app
npm ci
npm run build

# Run the server
dotnet run --project src/Authagonal.Server

Docker Build

# Server image (multi-stage: builds SPA + .NET in one image)
docker build -t authagonal .

# Migration tool
docker build -f Dockerfile.migration -t authagonal-migration .

As a Library (NuGet)

Reference the Authagonal packages in your own ASP.NET Core project:

<PackageReference Include="Authagonal.Server" Version="x.y.z" />
<PackageReference Include="Authagonal.AzureProvider" Version="x.y.z" />

The storage provider package is pluggable: Authagonal.AzureProvider for Azure Table Storage (the default AddAuthagonal() wiring), or Authagonal.AwsProvider for DynamoDB / S3 / Secrets Manager, see AWS backend below.

Then compose it into your Program.cs:

builder.Services.AddSingleton<IAuthHook, MyAuditHook>();   // Custom hook
builder.Services.AddSingleton<IEmailService, MyEmailService>(); // Custom email
builder.Services.AddAuthagonal(builder.Configuration);

var app = builder.Build();
app.UseAuthagonal();
app.MapAuthagonalEndpoints();
app.MapFallbackToFile("index.html");
app.Run();

See Extensibility for all override points and demos/custom-server/ for a complete example.

Email

The built-in Resend sender activates automatically when Email:ResendApiKey and Email:SenderEmail are configured, no service registration needed. Without any IEmailService, verification and password-reset emails are silently discarded, and because login requires a confirmed email by default, self-registered users can never sign in (UseAuthagonal logs a warning at startup). Either set the Email:* keys, register your own IEmailService before AddAuthagonal(), or list your domains in Auth:AutoConfirmEmailDomains to skip verification (dev/test only). See Configuration → Email.

AWS backend

To run on AWS instead of Azure, reference Authagonal.AwsProvider and register the AWS bundle before AddAuthagonal(), those registrations are what make AddAuthagonal() skip its Azure Table Storage wiring:

using Authagonal.AwsProvider;

builder.Services.AddAuthagonalAwsStorage(
    dynamoDb,                // IAmazonDynamoDB — required
    secretsManager,          // IAmazonSecretsManager — optional; replaces the plaintext ISecretProvider
    s3,                      // IAmazonS3 — optional; used for DataProtection keys
    "my-auth-keys-bucket");  // S3 bucket for the DataProtection key ring
builder.Services.AddAuthagonal(builder.Configuration);

The DynamoDB tables mirror the Azure layout one-for-one and are ensured on startup (idempotent, a no-op when they’re already provisioned by Terraform). Credentials resolve via the standard AWS chain (env / EC2 instance role / IRSA), so there is no connection-string-vs-managed-identity split, no Storage:* configuration is needed.

⚠️ S3 DataProtection keys. Without an S3 client + bucket, the ASP.NET Core Data Protection key ring is held in memory, fine for a single node in dev, but cookies and antiforgery tokens break on restart and across nodes in production. Always pass the S3 client and bucket for a production AWS deployment.

Login SPA (npm)

The login UI is published as an npm package for customization:

npm install @authagonal/login

The package ships compiled JS and CSS, import components and styles directly in your own React app. See Custom Server for a full walkthrough.

Production security checklist

Before exposing Authagonal to real traffic, confirm the following. Each item is detailed on the Configuration page.

Migration Tool

For migrating from Duende IdentityServer + SQL Server:

docker run authagonal-migration -- \
  --Source:ConnectionString "Server=...;Database=...;" \
  --Target:ConnectionString "DefaultEndpointsProtocol=https;..." \
  [--DryRun true] \
  [--MigrateRefreshTokens true]

See Migration for details.