Clients
In Faable Auth, a Client represents an application that authenticates users or requests authorization to access APIs: a Single Page Application (React, Vue, Angular), a native mobile app, a server-side web application, or a backend machine-to-machine service.
Clients are what initiate the OAuth 2.0 and OpenID Connect flows. You manage them from the Faable Dashboard , or create them programmatically with Dynamic Client Registration.
Creating a Client
Registering a client generates two credentials:
- Client ID — a public, unique identifier. Safe to ship in client-side code (React, Expo); it tells Faable Auth which application is asking.
- Client Secret — a confidential string that proves the application’s identity. Never expose it in a SPA, a mobile binary, or anything a user can read. It belongs to backends only.
Types of Clients
Your architecture dictates the configuration and the flow:
| Client type | Where the code runs | Secret? | Flow |
|---|---|---|---|
| Single Page App | The browser (React, Vue, Angular) | ❌ | Authorization Code + PKCE |
| Native / Mobile | The user’s device (iOS, Android, React Native) | ❌ | Authorization Code + PKCE |
| Regular Web App | Your server (Express, Next.js server components) | ✅ | Authorization Code |
| Machine to Machine | A backend service or worker, no human involved | ✅ | Client Credentials |
| Device / TV / CLI | An input-constrained device | ❌ | Device Code |
Faable Auth enforces PKCE with S256 — it advertises no other code challenge method — so public clients are covered whether or not a secret is present.
Client Configuration
Security boundaries
- Allowed Callback URLs (
callbacks) — the whitelist of URLs Faable Auth may redirect to after login (e.g.https://myapp.com/callback). Prevents open-redirect abuse. - Allowed Logout URLs (
logout_urls) — where users may be sent after RP-Initiated Logout. - Allowed Web Origins (
web_origins) — origins (scheme://host[:port], no path — e.g.http://localhost:5173) permitted to make cross-origin calls to the token and passwordless endpoints. When the list is empty, any origin is allowed; fill it in to lock browser calls down to your own app. Your account’s auth domain is always allowed implicitly, so you only list your application origins. - Connections — which authentication methods (Google, passwordless, database…) this specific client may use. Set on each connection via its Enabled clients list.
Token lifetimes
| Setting | Effect |
|---|---|
refresh_token.token_lifetime | Lifetime of issued refresh tokens, in seconds. Default 2592000 (30 days). |
| Access token lifetime | Not a client setting — it comes from the API the token is issued for (token_lifetime), defaulting to 24 hours. |
refresh_token.expiration_modeandrefresh_token.infinite_token_lifetimeexist on the client object for Auth0 compatibility, but are not enforced today — onlytoken_lifetimegoverns how long a refresh token lives. Don’t rely on them to build a never-expiring session.
Client authentication at the token endpoint
POST /oauth/token accepts three methods, as published in your tenant’s discovery document:
token_endpoint_auth_method | How the client authenticates | For |
|---|---|---|
client_secret_basic | HTTP Basic header with client_id:client_secret (the default) | Confidential clients |
client_secret_post | client_id + client_secret in the form body | Confidential clients |
none | No secret — the PKCE code_verifier is the proof | Public SPA and native clients |
Application metadata
Optional fields, mostly consumed by consent screens and by tooling: client_uri, logo_uri, tos_uri, policy_uri, contacts, application_type (web | native), software_id, software_version.
Front-Channel Logout
A client may register a frontchannel_logout_uri: Faable loads it in a hidden iframe when the user logs out of the OP, so your application can clear its own session. Set frontchannel_logout_session_required to true and Faable includes iss and sid on that call, letting you scope the cleanup to the exact session. See Logout.
Dynamic Client Registration
Clients can be created over HTTP instead of through the dashboard, per OIDC Dynamic Client Registration 1.0 / RFC 7591 . This is what lets a third-party tool onboard itself against your tenant — MCP clients, IDE integrations and OAuth debuggers commonly expect it.
The endpoint is published in your discovery document as registration_endpoint:
curl -X POST 'https://your-domain.auth.faable.link/oidc/register' \
-H 'content-type: application/json' \
-d '{
"client_name": "My Tool",
"redirect_uris": ["https://tool.example.com/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"token_endpoint_auth_method": "client_secret_basic"
}'Response (201), per RFC 7591 §3.2.1 — this is the only time the secret is returned:
{
"client_id": "…",
"client_secret": "…",
"client_id_issued_at": 1751641200,
"client_secret_expires_at": 0,
"redirect_uris": ["https://tool.example.com/callback"],
"client_name": "My Tool",
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"token_endpoint_auth_method": "client_secret_basic",
"application_type": "web"
}Notes on behaviour:
redirect_urisis the only required field. Everything else defaults per spec:grant_typesto["authorization_code"],response_typesto["code"],token_endpoint_auth_methodtoclient_secret_basic,application_typetoweb.- Unsupported metadata is rejected, not silently accepted. Requesting a grant type Faable doesn’t implement returns
400. Supported grants areauthorization_code,refresh_token,client_credentials,urn:ietf:params:oauth:grant-type:device_code,urn:ietf:params:oauth:grant-type:token-exchangeand Auth0’s passwordless OTP grant. client_secret_expires_atis0— issued secrets don’t expire.- The client is bound to the tenant resolved from the request host, so register against the domain you actually want it to live in.
web_originsis accepted as a non-standard extra, with the same rules as in the dashboard.- Registration is not itself authenticated. Anyone who can reach your auth domain can create a client in your tenant — a new client grants no access on its own, but if that’s not a trade-off you want, keep an eye on
oauth.client.registerentries in your logs.
Next Steps
- Connections — the identity providers you attach to a client.
- Authorization Code Flow — the mechanics of the standard login flow.
- APIs — register the resource servers your clients request tokens for.
- Quickstarts — jump into working code, including FastAPI on the backend side.
Last updated on