Skip to content

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

PurposeMethodPath
DiscoveryGET/.well-known/openid-configuration
AuthorizationGET/oauth/authorize
TokenPOST/oauth/token
UserInfoGET / POST/oauth/userinfo
RevocationPOST/oauth/revoke
JWKSGET/oauth/jwks
End sessionGET/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

ScopeClaims / effectRule
openidsubRequired
profilepreferred_username, pictureOptional
stoatstoat_id, stoat_verifiedOptional; linked identity required
emailemail, email_verifiedOptional; user may refuse; verified address only
offline_accessRefresh-token eligibilityConfidential 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: fragment

Matching 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_request

A required parameter is missing, duplicated or malformed.

invalid_client

The client ID or Web client authentication is invalid or revoked.

invalid_grant

The code or refresh token is invalid, expired, reused, revoked or bound to another redirect/PKCE verifier.

unauthorized_client

This client cannot use the requested grant or response type.

unsupported_grant_type

V1 only accepts authorization_code and eligible Web refresh_token grants.

invalid_scope

A scope is unknown or not allowed for this client type.

access_denied

The user refused consent or access is suspended.

login_required / consent_required

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