Portal Community

Client Types

Passport distinguishes between two client types, each with different security requirements:

TypeDescriptionSecret StoragePKCE Required
ConfidentialServer-side apps (ASP.NET, Node.js backend) that can securely store a client secretServer environment variable or secrets managerRecommended
PublicSPAs (React, Angular), mobile apps — cannot securely store a secretN/A — no client secretRequired

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

ScopeRequired?Claims AddedNotes
openidYessub, iss, aud, expAlways request this
profileRecommendedname, given_name, family_nameDisplay name for UI
emailRecommendedemail, email_verifiedUser identification
rolesFor RBACroles[]Required for permission checks
tenantFor multi-tenanttenant_id, tenant_nameRequired for tenant-scoped APIs