Skip to content

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).

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)
StateWho can actNotes
DraftTeam memberPrivate; not visible to reviewers
Pending ReviewSystem / ReviewerPolicy engine runs on submission
Changes RequestedReviewerTeam resubmits directly back to Pending Review
ActiveSystem / ReviewerExternal provider provisioned
RejectedReviewer / Policy engineHard-line violation; fresh submission required
SuspendedReviewer or Org AdminReversible; live config preserved
DeprecatedReviewer or Org AdminClient still works; teams are warned to migrate

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.

FieldTypeEffect
blockedGrantTypesstring[]Any submission requesting these grant types is rejected
reservedScopePrefixesstring[]Scopes starting with these prefixes are rejected (e.g. "platform:")
maxAccessTokenLifetimeSecsnumber?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).

{
"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
}
FieldDescription
typeMust be "oidc"
allowedGrantTypesAllowed subset of grant types
approvedScopesAllowed scope strings (exact match)
redirectUriPatternsGlob patterns; * matches within a path segment, ** matches across segments
requirePkceIf true, submissions without PKCE route to review
maxAccessTokenLifetimeSecsPer-team ceiling (must be ≤ platform ceiling)
maxRefreshTokenLifetimeSecsPer-team refresh token ceiling
{
"type": "saml",
"allowedAcsUrlPatterns": ["https://*.example.com/saml/acs"],
"allowedEntityIdPatterns": ["urn:example:*"],
"releasableAttributes": ["email", "name", "groups"],
"requiredSignatureAlgorithm": "rsa-sha256"
}
FieldDescription
typeMust be "saml"
allowedAcsUrlPatternsGlob patterns for allowed ACS URLs
allowedEntityIdPatternsGlob patterns for allowed entity IDs (omit to allow all)
releasableAttributesAttribute names the SP may request
requiredSignatureAlgorithm"rsa-sha256" or "rsa-sha512"

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.

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)

There are two distinct template types with different behaviors.

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 + pkce for SPAs)
  • Token endpoint auth method (e.g. none for 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 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).

Config updates on an Active client go through a parallel change set. The live config keeps working during review.

  1. Team member navigates to the client registration and clicks Propose Change.
  2. Policy engine runs on the new config.
  3. If auto-approved: provider updated atomically.
  4. If needs review: review request created; live config unchanged until reviewer approves.
  5. 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.

  1. 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.

  2. Create a policy profile (org admin)

    Go to Settings → Organization → Policy Profiles → New Profile. Choose client type (oidc or saml) 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.

  3. 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.

  4. 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.

  5. 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.

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.

ActionResult
ApproveClient provisioned in external provider; status → Active
Request ChangesStatus → Changes Requested; reason sent to team
RejectStatus → Rejected (terminal); reason recorded

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).

RoleCan submitCan reviewCan manage profilesCan set platform policy
Member
Reviewer
Org Admin / Owner✓ (org-scoped)
Instance Admin✓ (global + org)