Tokens, refresh and revoke
What the token endpoint returns, how long it lasts, and how to keep a user signed in or sign them out.
Lifetimes
| Token | Looks like | Lasts |
|---|---|---|
| Access token | cat_… | 1 hour (expires_in says exactly) |
| Refresh token | crt_… | 60 days, and replaced on every use |
| ID token | JWT (RS256) | 1 hour |
| Authorization code | — | 5 minutes, single use |
Treat tokens as opaque strings; the prefixes may change. Send access tokens only in the
Authorization: Bearer header, never in a URL.
Refresh
curl -X POST https://sso.castyr.cloud/oauth/token \
-u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-d grant_type=refresh_token \
-d refresh_token=crt_…Public clients send client_id instead of -u. You may pass scope to ask for fewer scopes than before,
but never more. The response has a new refresh token: store it and throw the old one away.
Rotation is strict
If an old refresh token is ever used again, Castyr treats it as stolen and revokes every token in that chain, which signs the user out of your app. If you refresh from more than one process, make sure only one of them does it at a time.
Refreshing fails with invalid_grant when the user has removed your app's access or has been banned; send
them through sign-in again. A disabled app gets invalid_client.
Revoke (sign out)
curl -X POST https://sso.castyr.cloud/oauth/revoke \
-u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-d token=crt_… \
-d token_type_hint=refresh_tokenRevoking either token revokes the whole chain it belongs to. For TVs and bots, it also removes the link from
the user's Devices page (and from Connected apps, if it was their last one). The endpoint always answers
200 {}, even for unknown tokens, so it can't be used to test whether a token is valid. You can only revoke
your own app's tokens.