OAuth Clients
Register an OAuth client so your app can request tokens via Hosted Login or any OIDC-compatible flow.
Overview
An OAuth client in Canopy is a registered OAuth 2.0 credential — the client_id + client_secret pair your app uses to request tokens on behalf of an end user. Distinct from the platform's Application concept: in the Account → Application → Environment hierarchy, an Application is the unit your access-control model lives under; an OAuth client is configuration that lives inside a single Environment. You'll typically register one OAuth client per Environment (e.g. one in development, one in staging, one in production). From each registration you receive a client_id (a public UUID) and a client_secret (a backend-only credential, shown once at creation). Both values feed into the OAuth flows covered on the Authentication page — Hosted Login uses them to exchange an authorization code for an access token, ID token, and refresh token. A user signing in through a given OAuth client always authenticates into that client's Environment.
Register from the dashboard
Registering from the dashboard is the fastest path. The form mirrors the API surface but applies sensible defaults so you only fill in what's specific to your app.
Dashboard → Integrations → OAuth Clients and click Register OAuth Client.client_id and client_secret — copy the secret to your secrets manager before closing the dialog. The secret is only shown once.Register via the API
If you'd rather provision OAuth clients from a script or CI pipeline, the same operation is available on the portal API. The endpoint is env-scoped — register against the Account / Application / Environment you want the client to live in. Authentication uses the portal Bearer JWT for the user creating the client.
POST /portal/v1/accounts/:accountSlug/applications/:appSlug/environments/:envSlug/oauth-clientsRequest
curl -X POST https://auth.canopy-io.com/portal/v1/accounts/acme/applications/web/environments/production/oauth-clients \
-H "Authorization: Bearer $PORTAL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My App (production)",
"redirect_uris": ["https://app.example.com/auth/callback"]
}'Response
{
"data": {
"client_id": "0d4b7e90-…",
"client_secret": "e3b0c44…",
"name": "My App (production)"
}
}The client_secret in the response is the only time you'll see it in plaintext. The data envelope is the standard shape for every /portal/v1 endpoint that returns a single resource.
Configuration fields
Every OAuth client is configured with the same handful of fields — required ones are enforced by the API, optional ones fall back to sensible defaults.
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | A human-readable label for the OAuth client — shown in the dashboard list, never returned in tokens. Make it descriptive enough to identify in a list (e.g. Mobile app (prod), Internal admin). |
redirect_uris | Yes | — | Array of URLs (at least one). Every URL your app may redirect to after Hosted Login completes. The match is exact — no wildcards, no trailing-slash forgiveness. Any scheme is allowed and a public TLD is not required, so http://localhost:3000/callback is valid for development. |
scopes | No | ["openid", "profile", "email"] | OIDC scopes the OAuth client is allowed to request. The dashboard form omits this and uses the default; the API accepts an explicit array. Add org to include account_id, application_id, and environment_id in the ID token. |
invite_redirect_url | No | Canopy-hosted page | Where to send a user after they accept an invite issued through this OAuth client. |
What you receive
Two values are returned at creation time. They live in different places and have very different security properties.
| Field | Visibility | Description |
|---|---|---|
client_id | Public | A UUID. Safe to embed in your frontend, in URL query strings, in logs. Identifies your OAuth client to Canopy on every authorization request. |
client_secret | Backend-only | A high-entropy random string. Stored hashed at rest by Canopy and never returned again after creation. Used by your backend to authenticate the code-for-token exchange at /oauth/token. |
The client_secret is shown only once, at creation, in the registration dialog or API response. Canopy stores a bcrypt hash and there is no way to retrieve the plaintext later. If you don't capture it before closing the dialog, you'll need to delete and re-register the OAuth client.
Manage OAuth clients
Beyond create, the portal API supports listing, fetching, updating metadata, and deleting OAuth clients. PATCH can change the name, redirect URIs, scopes, and invite redirect URL — but not the secret. To rotate a compromised secret, delete the OAuth client and register a new one. Full details on each endpoint are in the API Reference.