Reference
OAuth 2.0 and OpenID Connect reference
The issuer is https://stoatboard.com. Read discovery at runtime instead of copying endpoint URLs into application logic.
Endpoints
| Purpose | Method | Path |
|---|---|---|
| Discovery | GET | /.well-known/openid-configuration |
| Authorization | GET | /oauth/authorize |
| Token | POST | /oauth/token |
| UserInfo | GET / POST | /oauth/userinfo |
| Revocation | POST | /oauth/revoke |
| JWKS | GET | /oauth/jwks |
| End session | GET | /oauth/logout |
Authorization does not enable CORS. Token, UserInfo and revocation CORS is limited to registered SPA origins. Server clients do not depend on browser CORS.
Supported flow and clients
- CONFIDENTIAL_WEB
- Authorization Code, mandatory PKCE S256, client_secret_basic, rotating refresh tokens when offline_access is granted.
- PUBLIC_SPA
- Authorization Code, mandatory PKCE S256, token endpoint auth method none, no refresh token in V1.
Response type is code. Implicit, password, client credentials, device, native-app and dynamic registration flows are disabled.
Scopes and claims
| Scope | Claims / effect | Rule |
|---|---|---|
| openid | sub | Required |
| profile | preferred_username, picture | Optional |
| stoat | stoat_id, stoat_verified | Optional; linked identity required |
| email, email_verified | Optional; user may refuse; verified address only | |
| offline_access | Refresh-token eligibility | Confidential Web only |
sub is a stable opaque StoatBoard user identifier. Key external accounts by issuer plus subject; never by username, email or Stoat ID.
Token and interaction lifetimes
- Authorization code60 seconds; single use
- Access token10 minutes; opaque
- ID token10 minutes; RS256 JWT with kid
- Refresh token30 days; opaque and rotating
- Authorization interaction10 minutes
- Stored grantUp to 1 year, subject to revocation
Redirect URI rules
https://example.com/auth/callback accepted
http://localhost:3000/callback accepted for local development
http://127.0.0.1:5173/callback accepted for local development
https://*.example.com/callback rejected: wildcard
https://[email protected]/callback rejected: userinfo
https://example.com/callback#fragment rejected: fragmentMatching is exact after URL normalization. HTTPS is required except for localhost, 127.0.0.1 and [::1]. International domain names are parsed as URLs and displayed with their exact registered host.
Default portal limits
10 applications per owner, 10 clients per application, 20 redirects per client and 30 developer mutations per hour. These anti-abuse limits are configurable and may be reduced during an incident.
Errors
invalid_requestA required parameter is missing, duplicated or malformed.
invalid_clientThe client ID or Web client authentication is invalid or revoked.
invalid_grantThe code or refresh token is invalid, expired, reused, revoked or bound to another redirect/PKCE verifier.
unauthorized_clientThis client cannot use the requested grant or response type.
unsupported_grant_typeV1 only accepts authorization_code and eligible Web refresh_token grants.
invalid_scopeA scope is unknown or not allowed for this client type.
access_deniedThe user refused consent or access is suspended.
login_required / consent_requiredThe request used a prompt mode that prevents the required interaction.
At the authorization endpoint, protocol errors return only to a valid pre-registered redirect URI; otherwise StoatBoard shows a local error. Never redirect an unvalidated URI. Token errors use JSON and an appropriate HTTP status.