Skip to content

OAuth2 clients

Registering public and confidential OAuth2 clients, grant types, redirect URIs, and secrets.

Intended audience: Stakeholders, Business analysts, Solution architects, Developers, Testers

Learning outcomes by role

Stakeholders

  • Understand first-party versus third-party OAuth clients for partnerships.

Business analysts

  • Capture client registration, redirect URI, and scope requirements.

Solution architects

  • Secure client secrets, rotation, and network access to token endpoints.

Developers

  • Register and maintain OAuth2 clients via platform admin APIs.

Testers

  • Exercise token grants and client revocation scenarios.

Register OAuth2 clients so applications can use authorization code, refresh, and password grants against your Cadence deployment.

  • Trust boundaries — Each client ties redirect URIs and grant types to a specific product surface; misconfiguration can leak tokens to the wrong origin.
  • Secrets — Confidential clients carry secrets; public clients rely on PKCE instead of a shared secret.
  • Environments — Register separate redirect URI sets per dev/staging/prod; acceptance tests should cover mistyped URIs.
  • Grants — Document which flows (authorization code, refresh, password) are approved for your org’s policy.
  • Client rows live in PostgreSQL and are consumed by the OAuth2 token and authorization endpoints (cadence.api.oauth2 and related modules).
  • Network access to /oauth2/* (and /.well-known/openid-configuration) should follow the same TLS and WAF rules as the rest of the API.
  • Admin APIs with cadence:system:oauth_clients:read (list) and cadence:system:oauth_clients:write (create)
  • Known redirect URIs for each environment (dev/staging/prod)
  1. Choose a client_id and register redirect_uris for your app (include dev and staging URLs as needed).
  2. Enable authorization_code (and refresh_token if using refresh) in allowed_grant_types.
  3. For server-side apps, set client_type to confidential and supply a client_secret at creation; store the secret securely.
  4. For SPAs, use public clients with PKCE (code_challenge / code_verifier).
  5. Configure your app to discover endpoints from GET /.well-known/openid-configuration at the Cadence API base URL.

| Field | Type | Meaning | | --------------------- | -------------------------- | -------------------------------------------------------------- | | client_id | string | Unique identifier (e.g. my-spa) | | name | string | Human-readable label | | client_type | public or confidential | Confidential clients require client_secret on token requests | | is_first_party | boolean | Metadata for your UX or policy | | redirect_uris | string[] | Allowed redirect URLs — exact match on /oauth2/authorize | | allowed_grant_types | string[] | e.g. authorization_code, refresh_token, password | | allowed_scopes | string[] | Optional filter; empty means “allow requested scope” | | is_active | boolean | Soft-disable the client |

cadence/api/admin/schemas.py
class OAuth2ClientCreate(BaseModel):
client_id: str = Field(..., min_length=2, max_length=255)
name: str
client_type: str = Field("confidential", pattern="^(public|confidential)$")
is_first_party: bool = False
redirect_uris: List[str] = Field(default_factory=list)
allowed_grant_types: List[str] = Field(default_factory=list)
allowed_scopes: List[str] = Field(default_factory=list)
client_secret: Optional[str] = None

| Symptom | Cause | Fix | | ------------------------- | ------------------------------------------------------------- | ------------------------------------------------ | | invalid_client on token | Wrong client_id or missing client_secret for confidential | Verify client id and secret | | invalid_redirect_uri | URI not in redirect_uris (must be exact match) | Add the exact URI including trailing slash | | Consent fails | User must be logged in for POST /oauth2/consent/decision | Ensure the user session is active before consent |