Getting Started

This walkthrough takes a new TokenIDP environment from an empty host to a working browser sign-in flow. By the end of the setup:

  • the TokenIDP host should be running
  • the first tenant and administrator account should exist
  • browser and API origins should be configured
  • a React client should complete Authorization Code Flow with PKCE

Prerequisites

Before starting, ensure the following are available:

  • .NET 10 SDK installed for running the TokenIDP host
  • SQL Server/PostgreSQL connectivity for the TokenIDP database
  • A local development environment capable of running ASP.NET Core and React applications

Setup path

1. Create an ASP.NET Core Web API project

Create a new ASP.NET Core Web API project with the .NET 10 SDK.

dotnet new webapi -n TokenIDP.Host -f net10.0
cd TokenIDP.Host

2. Install the NuGet package

dotnet add package TokenIDP.Server

3. Configure appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=.;Database=TokenIDP;Trusted_Connection=True;TrustServerCertificate=True"
  },
  "TokenOptions": {
    "Issuer": "https://localhost:5001",
    "Audience": "tokenidp.admin.api"
  },
  "Bootstrap": {
    "Enable": true,
    "ClientId": "tokenidp-admin",
    "RedirectUri": "http://localhost:3000/auth/callback",
    "LogoutRedirectUri": "http://localhost:3000/logout/callback",
    "AdminName": "admin@tokenidp.local",
    "AdminTempPassword": "ChangeThisTempPassword123!"
  },
  "TenantResolution": {
    "AllowedRootDomains": ["example.com"],
    "SystemHostAliases": ["admin.example.com"],
    "AllowedDevelopmentHosts": ["localhost"],
    "DefaultTenant": "system",
    "AllowQueryInStaging": true,
    "AllowHeaderInStaging": false,
    "LookupCacheMinutes": 15,
    "InvalidHostThrottleWindowSeconds": 60,
    "InvalidHostThrottleMaxAttempts": 20
  },
  "Cors": {
    "AllowedOrigins": [
      "http://localhost:3000"
    ]
  },
  "Security": {
    "KeyBase64": "2YF1GQ7K2c1mKqv9n8kLxYF3z6YF1GQ7K2c1mKqv9n8=",
    "KeyId": "default"
  }
}

Bootstrap:RedirectUri and Bootstrap:LogoutRedirectUri do not need to be the same URL. They are separate allow-list entries:

  • Bootstrap:RedirectUri must match the Admin Portal redirectUri.
  • Bootstrap:LogoutRedirectUri must match the Admin Portal postLogoutRedirectUri.

Keep token signing private keys out of appsettings.json. For local development, store the signing key path with .NET user secrets:

dotnet user-secrets init
dotnet user-secrets set "TokenOptions:KeyPath" "D:\TokenIDP\signing-key.pem"

The PEM file should contain an RSA private key and should not be committed to source control. For supported local and production signing-key options, see Key Management.

4. Add TokenIDP to Program.cs

The current host integration uses AddTokenIDPServices(...) and UseTokenIDPAsync(...).

using TokenIDP.Core.Foundation.Options;
using TokenIDP.Server.ApplicationSetup;

var builder = WebApplication.CreateBuilder(args);

builder.AddTokenIDPServices("DefaultConnection", "tokenidp.admin.api");

var corsOptions = builder.Configuration
    .GetSection(CorsOptions.SectionName)
    .Get<CorsOptions>() ?? new CorsOptions();

var app = builder.Build();

app.UseExceptionHandler("/error");

await app.UseTokenIDPAsync(corsOptions.AllowedOrigins, "DefaultConnection");

await app.RunAsync();

5. Understand first-run bootstrap

When Bootstrap:Enable is true, TokenIDP creates the initial Tenant, Application, and admin user if they do not already exist. That is convenient for local development and first-time installation, but it should be treated as a one-time setup path.

Production warning: do not leave bootstrap enabled after the first successful production deployment. Treat the bootstrap values as privileged seed credentials and rotate the temporary admin password immediately.

For detailed startup rules, post-install behavior, and production risk guidance, see System Bootstrap Behavior.

6. Configure CORS

TokenIDP uses origin-based CORS policies for browser applications. Before testing authentication flows, determine which browser origins should be allowed to access the platform.

Typical origins include:

  • Admin Portal origin, for example https://admin.example.com
  • Local development SPA origin, for example http://localhost:3000
  • Production application origins, for example https://app.example.com

Only browser-based applications require CORS configuration. Server-to-server communication is not subject to browser CORS restrictions.

7. Set up the React Admin Portal with Authorization Code + PKCE

The TokenIDP Admin Portal is distributed as a prebuilt static React application.

  • Open the TokenIDP GitHub repository.
  • Download the TokenIDP.AdminPortal.<version>.zip asset from the Admin Portal release workflow artifacts.
  • Extract the ZIP package.
  • Deploy the extracted files to your preferred static hosting platform, such as IIS, Nginx, Azure Static Web Apps, Amazon S3 + CloudFront, or any other static hosting provider.

Configuration

The Admin Portal uses Authorization Code Flow with PKCE through the bundled tokenidp-react SDK.

  • No rebuild is required for each deployment environment.
  • No .env file changes are required after the release package is built. The .env files are only used during the React build process.
  • Runtime configuration is provided through the config.json file included in the deployment bundle.
  • Update config.json after deployment to configure environment-specific settings such as TokenIDP endpoints and client configuration.

Example config.json:

{
  "deploymentEnvironment": "development",
  "baseUrl": "https://localhost:5001",
  "authority": "https://localhost:5001",
  "tenantPropagationMode": "none",
  "tenantQueryParameter": "tenant",
  "userPermissionsPath": "admin/user/permissions",
  "clientId": "tokenidp-admin",
  "redirectUri": "http://localhost:3000/auth/callback",
  "postLoginRedirectUri": "/dashboard",
  "postLogoutRedirectUri": "http://localhost:3000/logout/callback",
  "scope": "openid profile tokenidp.admin.write tokenidp.admin.read"
}

Configure config.json

Update the runtime configuration before deployment:

  • Set baseUrl to the TokenIDP hosted URL.
  • Set authority to the same TokenIDP hosted URL.
  • Set redirectUri to the Admin Portal callback URL. This must exactly match Bootstrap:RedirectUri.
  • Set postLogoutRedirectUri to the Admin Portal logout callback URL. This must exactly match Bootstrap:LogoutRedirectUri.
  • Ensure clientId matches the Admin Portal client configured in appsettings.json under Bootstrap:ClientId and registered in TokenIDP.

Configure Static Hosting

Before deploying the Admin Portal:

  • Configure SPA route rewriting.
  • Rewrite all unknown routes to index.html.
  • Ensure browser refreshes continue to work for client-side routes.
  • Ensure direct navigation works for bookmarked URLs.

Common routes include:

  • /auth/callback
  • /dashboard
  • /applications
  • /users
  • /roles

Register Redirect URIs in TokenIDP

For the Admin Portal client, register the following redirect URIs:

  • http://localhost:3000/auth/callback

Register the following post-logout redirect URI:

  • http://localhost:3000/logout/callback

Common Pitfalls

  • Keeping Bootstrap:Enable turned on after initialization.
  • Reusing a development signing key in production.
  • Putting a private signing key directly in appsettings.json instead of using user secrets, a protected file path, or certificate configuration.
  • Registering http://localhost:3000/ in the client but sending http://localhost:3000/callback in the authorization request.
  • Allowing the SPA origin in CORS but forgetting the Admin Portal origin.
  • Using the old AddTresorAuthServices or UseTresorAuthAsync names in a current host.

Troubleshooting

  • If startup throws a signing-key error, verify your local TokenOptions:KeyPath user secret or configure production TokenOptions:CertificateThumbprint / TokenOptions:CertificateSubjectName.
  • If the SPA loops between callback and login, inspect the browser network trace for a redirect URI mismatch or missing code_verifier.
  • If token validation fails in your API, compare Issuer, Audience, and JWKS settings on both sides.