Client Registration Workflow
The client registration workflow gates OIDC and SAML client provisioning behind a three-tier policy engine with optional human review. Clients move through a defined lifecycle before they are written to the external provider (Ory Hydra, Auth0, Entra ID, RFC 7592).
Lifecycle states
Section titled “Lifecycle states”Draft → Pending Review → Active ↓ ↑ Changes Requested → (resubmit) ↓ Rejected (terminal — new submission required)
Active → Suspended (reversible, config preserved)Active → Deprecated (end-of-life signal, still functional)| State | Who can act | Notes |
|---|---|---|
| Draft | Team member | Private; not visible to reviewers |
| Pending Review | System / Reviewer | Policy engine runs on submission |
| Changes Requested | Reviewer | Team resubmits directly back to Pending Review |
| Active | System / Reviewer | External provider provisioned |
| Rejected | Reviewer / Policy engine | Hard-line violation; fresh submission required |
| Suspended | Reviewer or Org Admin | Reversible; live config preserved |
| Deprecated | Reviewer or Org Admin | Client still works; teams are warned to migrate |
Policy model
Section titled “Policy model”Three tiers, each a strict subset of the tier above.
Tier 1 — Platform Policy (global hard limits)
Section titled “Tier 1 — Platform Policy (global hard limits)”Set by instance admins at Settings → Instance → Platform Policy.
Violations cause immediate rejection — no human review.
| Field | Type | Effect |
|---|---|---|
blockedGrantTypes | string[] | Any submission requesting these grant types is rejected |
reservedScopePrefixes | string[] | Scopes starting with these prefixes are rejected (e.g. "platform:") |
maxAccessTokenLifetimeSecs | number? | Ceiling on token lifetime for all teams |
{ "blockedGrantTypes": ["implicit", "password"], "reservedScopePrefixes": ["platform:", "internal:"], "maxAccessTokenLifetimeSecs": 86400}Tier 2 — Team Policy Profile (per-team bounds)
Section titled “Tier 2 — Team Policy Profile (per-team bounds)”Created by org admins at Settings → Organization → Policy Profiles, then assigned to teams.
Submissions outside these bounds route to human review (not auto-approved, not rejected).
OIDC profile constraints
Section titled “OIDC profile constraints”{ "type": "oidc", "allowedGrantTypes": ["authorization_code", "refresh_token"], "approvedScopes": ["openid", "profile", "email", "offline_access"], "redirectUriPatterns": ["https://*.example.com/*", "https://app.myco.io/callback"], "requirePkce": true, "maxAccessTokenLifetimeSecs": 3600, "maxRefreshTokenLifetimeSecs": 2592000}| Field | Description |
|---|---|
type | Must be "oidc" |
allowedGrantTypes | Allowed subset of grant types |
approvedScopes | Allowed scope strings (exact match) |
redirectUriPatterns | Glob patterns; * matches within a path segment, ** matches across segments |
requirePkce | If true, submissions without PKCE route to review |
maxAccessTokenLifetimeSecs | Per-team ceiling (must be ≤ platform ceiling) |
maxRefreshTokenLifetimeSecs | Per-team refresh token ceiling |
SAML profile constraints
Section titled “SAML profile constraints”{ "type": "saml", "allowedAcsUrlPatterns": ["https://*.example.com/saml/acs"], "allowedEntityIdPatterns": ["urn:example:*"], "releasableAttributes": ["email", "name", "groups"], "requiredSignatureAlgorithm": "rsa-sha256"}| Field | Description |
|---|---|
type | Must be "saml" |
allowedAcsUrlPatterns | Glob patterns for allowed ACS URLs |
allowedEntityIdPatterns | Glob patterns for allowed entity IDs (omit to allow all) |
releasableAttributes | Attribute names the SP may request |
requiredSignatureAlgorithm | "rsa-sha256" or "rsa-sha512" |
Tier 3 — Client Configuration
Section titled “Tier 3 — Client Configuration”What the team submits. Auto-approved when it falls entirely within Tier 2 bounds. Routes to human review when it falls outside Tier 2 bounds. Rejected immediately on any Tier 1 violation.
Auto-approve vs human review
Section titled “Auto-approve vs human review”Submit config │ ▼Platform policy check │ ├─ violation → Rejected immediately (no review queue entry) │ ▼Team profile check │ ├─ no profile assigned → Needs review ├─ config outside profile → Needs review (violations listed in review request) │ └─ config within profile → Auto-approved → Active (external provider provisioned immediately)Templates
Section titled “Templates”There are two distinct template types with different behaviors.
Framework templates (starting config)
Section titled “Framework templates (starting config)”When creating a new registration, the form offers a template picker populated from the cerberauth/nacho registry — 67+ templates covering common frameworks and platforms (React, Next.js, Django, Spring Boot, Go, etc.).
Selecting a framework template pre-fills the client configuration:
- Grant types (e.g.
authorization_code + pkcefor SPAs) - Token endpoint auth method (e.g.
nonefor public clients) - Requested scopes (e.g.
openid profile email)
Framework templates are starting configurations only — the registration is still created as a Draft and follows the normal review lifecycle. Redirect URIs and other app-specific fields must be filled in before submission.
The template list is fetched from the nacho repository and cached for 24 hours.
Org / instance templates (fast path)
Section titled “Org / instance templates (fast path)”Org and instance templates bypass policy evaluation entirely. A submission from one of these templates is auto-approved immediately without entering the review queue.
These are created by:
- Instance admins — global templates visible to all orgs (e.g. “SPA with PKCE”, “M2M Client Credentials”)
- Org admins — org-scoped templates for their own teams
Manage at Settings → Organization → Templates (org-scoped) or Settings → Instance → Templates (global).
Change sets
Section titled “Change sets”Config updates on an Active client go through a parallel change set. The live config keeps working during review.
- Team member navigates to the client registration and clicks Propose Change.
- Policy engine runs on the new config.
- If auto-approved: provider updated atomically.
- If needs review: review request created; live config unchanged until reviewer approves.
- Approved → atomic swap in external provider. Rejected → live config unchanged.
Only one open change set per client at a time. Submitting a new one supersedes any pending one.
Configuration guide
Section titled “Configuration guide”-
Set platform policy (instance admin)
Go to Settings → Instance → Platform Policy. Add blocked grant types (e.g.
implicit,password) and reserved scope prefixes (e.g.platform:,admin:). Save — takes effect on all future submissions immediately. -
Create a policy profile (org admin)
Go to Settings → Organization → Policy Profiles → New Profile. Choose client type (
oidcorsaml) and enter the JSON constraints (see format above). Save — version 1 is created.To update constraints later, open the profile and click New Version. Existing active clients referencing the old version are unaffected; only new submissions use the new version.
-
Assign profile to a team (org admin)
Go to Settings → Organization → Teams → [team name] → Policy. Select the profile for OAuth2/OIDC clients and/or for SAML clients. Save.
Teams without a profile assigned always route to human review.
-
Add reviewers (org admin)
Go to Settings → Organization → Members. Find the member and change their role to Reviewer. Reviewers see the Review Queue in the sidebar.
Instance admins (
users.role = 'admin') can always review regardless of org membership. -
Submit a client (team member)
Go to Registrations → New Registration. Optionally pick a framework template (e.g. “React SPA”, “Next.js App”) to pre-fill grant types, auth method, and scopes, or skip for a blank config. Choose client type and enter a name, then click Create Draft.
Fill in app-specific fields (redirect URIs, audience, etc.) and click Submit for Review. If auto-approved: client is live immediately. If routed to review: status shows Pending Review.
Review queue
Section titled “Review queue”Reviewers access pending submissions at /review. Each review shows the full proposed configuration, the policy evaluation result (which fields triggered review and why), and a comment thread.
| Action | Result |
|---|---|
| Approve | Client provisioned in external provider; status → Active |
| Request Changes | Status → Changes Requested; reason sent to team |
| Reject | Status → Rejected (terminal); reason recorded |
API / programmatic access
Section titled “API / programmatic access”All workflow operations are currently exposed as Next.js Server Actions. A REST API surface is not yet available but planned. For automated provisioning, use templates (which bypass the review queue on instantiation).
Roles reference
Section titled “Roles reference”| Role | Can submit | Can review | Can manage profiles | Can set platform policy |
|---|---|---|---|---|
| Member | ✓ | — | — | — |
| Reviewer | ✓ | ✓ | — | — |
| Org Admin / Owner | ✓ | ✓ | ✓ (org-scoped) | — |
| Instance Admin | ✓ | ✓ | ✓ (global + org) | ✓ |