Docs · Integrate

Refresh tokens

Keep users signed in for up to 30 days with rotating refresh tokens, and what happens when one is stolen.

Access and ID tokens last 15 minutes. To get new ones without sending the user back to sign in, ask for the offline_access scope and you’ll get a refresh token too.

Use a refresh token

POST /token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=gkr_01JB7Q…
&client_id=acme-notes

The response is the same shape as the first token response, with a new refresh token.

Rotation: every refresh token works once

Each time you use a refresh token, Gatekeep marks it used and gives you a new one. Always store the new one and throw the old one away.

If an old refresh token is ever used a second time, Gatekeep assumes it was stolen and revokes the whole chain: the old token, the new one and every token after it. Both the attacker and the real user have to sign in again. A passkey touch later, the real user is back; the attacker isn’t.

Two requests racing to refresh with the same token will trip this protection. Refresh in one place (your server, or one tab with a lock) and share the result.

Lifetimes

TokenLasts
Authorization code60 seconds, single use
Access token, ID token15 minutes
Refresh token30 days, single use, rotated

Narrowing scope

You can ask for fewer scopes on refresh by sending scope. You can’t ask for more than the user originally granted; that returns invalid_scope.