Passport
OIDC Client Setup
Register your application as an OIDC client in Passport — configure the client ID, client secret, redirect URIs, scopes, and token lifetime settings.
Client Types
Passport distinguishes between two client types, each with different security requirements:
| Type | Description | Secret Storage | PKCE Required |
|---|---|---|---|
| Confidential | Server-side apps (ASP.NET, Node.js backend) that can securely store a client secret | Server environment variable or secrets manager | Recommended |
| Public | SPAs (React, Angular), mobile apps — cannot securely store a secret | N/A — no client secret | Required |
OIDCClientConfiguration Model
// The configuration model for an OIDC consumer registration
public class OIDCClientConfiguration
{
public required string ClientId { get; init; }
public string? ClientSecret { get; init; } // null for public clients
public required string[] RedirectUris { get; init; }
public string[] PostLogoutRedirectUris { get; init; } = [];
public required string[] AllowedScopes { get; init; }
public required string[] GrantTypes { get; init; }
public bool RequirePkce { get; init; } = true;
public bool RequireMfa { get; init; } = false;
public int AccessTokenLifetimeSeconds { get; init; } = 900;
public int RefreshTokenLifetimeSeconds { get; init; } = 604800;
public bool AllowRefreshToken { get; init; } = true;
public bool RefreshTokenRotation { get; init; } = true;
public string TenantId { get; init; } = string.Empty;
public string DisplayName { get; init; } = string.Empty;
}
Registering a Confidential Client (ASP.NET Backend)
POST /passport/admin/clients
Authorization: Bearer {admin-token}
Content-Type: application/json
{
"clientId": "workflow-api-prod",
"clientType": "confidential",
"clientSecret": "generate",
"displayName": "Workflow API (Production)",
"redirectUris": [
"https://api.bizfirst.example.com/auth/callback"
],
"postLogoutRedirectUris": [
"https://api.bizfirst.example.com/"
],
"allowedScopes": ["openid", "profile", "email", "roles", "tenant"],
"grantTypes": ["authorization_code", "refresh_token", "client_credentials"],
"requirePkce": true,
"accessTokenLifetimeSeconds": 900,
"refreshTokenLifetimeSeconds": 604800,
"tenantId": "tenant-abc"
}
// Response
{
"clientId": "workflow-api-prod",
"clientSecret": "clt_sk_xxxxxxxxxxxxxxxxxxxxxxxx", // store this securely
"createdAt": "2026-05-25T10:00:00Z"
}
Store Client Secrets Securely
The client secret is shown only once in the creation response. Store it in a secrets manager (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault) — never in source code or configuration files. If the secret is lost, generate a new one via the Admin API.
Registering a Public Client (React SPA)
POST /passport/admin/clients
Authorization: Bearer {admin-token}
Content-Type: application/json
{
"clientId": "flow-studio-spa",
"clientType": "public",
"displayName": "Flow Studio (SPA)",
"redirectUris": [
"https://studio.bizfirst.example.com/auth/callback",
"https://studio.bizfirst.example.com/auth/silent-renew"
],
"postLogoutRedirectUris": [
"https://studio.bizfirst.example.com/"
],
"allowedScopes": ["openid", "profile", "email", "roles", "tenant"],
"grantTypes": ["authorization_code", "refresh_token"],
"requirePkce": true,
"accessTokenLifetimeSeconds": 900,
"refreshTokenLifetimeSeconds": 86400,
"tenantId": "tenant-abc"
}
// No clientSecret — public clients use PKCE instead
appsettings.json Integration
For ASP.NET Core applications using Go.Essentials, configure the OIDC client in appsettings.json:
{
"Passport": {
"Authority": "https://passport.bizfirst.ai",
"ClientId": "workflow-api-prod",
"ClientSecret": "${PASSPORT_CLIENT_SECRET}",
"Scopes": ["openid", "profile", "email", "roles", "tenant"],
"RequirePkce": true,
"ValidateIssuer": true,
"ValidateAudience": true,
"ValidIssuers": ["https://passport.bizfirst.ai"],
"TokenValidationParameters": {
"ClockSkewSeconds": 60,
"RequireExpirationTime": true,
"RequireSignedTokens": true
}
}
}
Scope Reference
| Scope | Required? | Claims Added | Notes |
|---|---|---|---|
openid | Yes | sub, iss, aud, exp | Always request this |
profile | Recommended | name, given_name, family_name | Display name for UI |
email | Recommended | email, email_verified | User identification |
roles | For RBAC | roles[] | Required for permission checks |
tenant | For multi-tenant | tenant_id, tenant_name | Required for tenant-scoped APIs |