Follow-up to #254 (PKCE for RS OAuth). We deliberately deferred this to keep #254 focused.
Goal
Decouple authorization/grant validity from access-token validity: short-lived access tokens that renew automatically, while the grant stays valid for the user-selected period (never / 1 month / 1 day) and remains revocable per device.
Today, with the implicit and PKCE flows, the access token lives exactly as long as the authorization. When it expires, the remoteStorage client gets a 401, emits an UnauthorizedError, and the user must reconnect through the OAuth dialog (which mints a new per-device token).
PKCE itself does not refresh anything — RFC 7636 only secures the authorization-code exchange. Refresh tokens are a separate OAuth mechanism, and remoteStorage 1.0 does not define a refresh flow.
Scope
akkounts
Issue a refresh_token alongside the access token in the PKCE token exchange (POST /rs/oauth/token).
Support grant_type=refresh_token at the token endpoint: validate the refresh token, rotate the access token (update Redis authorizations:<cn>:<token>), and return the new token.
Keep the grant alive until the user-selected authorization expiry (RemoteStorageAuthorization#expire_at), independent of the access-token TTL.
Store/rotate refresh tokens securely (hashed at rest; rotation + reuse detection per RFC 9700).
Decide the access-token TTL and how Liquor Cabinet stays consistent during rotation.
remoteStorage.js (separate repo)
Automatic refresh on 401 currently exists only in the Dropbox backend (src/dropbox.ts, guarded by this.refreshToken). The generic remoteStorage backend only emits UnauthorizedError (src/remotestorage.ts).
Mirror the Dropbox refresh path in the generic backend so apps benefit automatically.
Until that ships, refresh tokens would be inert for the main client, which is why this was deferred.
draft-dejong-remotestorage-27 §10/§10.1 (defines bearer tokens, no refresh)
Follow-up to #254 (PKCE for RS OAuth). We deliberately deferred this to keep #254 focused.
## Goal
Decouple **authorization/grant validity** from **access-token validity**: short-lived access tokens that renew automatically, while the grant stays valid for the user-selected period (never / 1 month / 1 day) and remains revocable per device.
Today, with the implicit and PKCE flows, the access token lives exactly as long as the authorization. When it expires, the remoteStorage client gets a `401`, emits an `UnauthorizedError`, and the user must reconnect through the OAuth dialog (which mints a new per-device token).
PKCE itself does **not** refresh anything — RFC 7636 only secures the authorization-code exchange. Refresh tokens are a separate OAuth mechanism, and remoteStorage 1.0 does not define a refresh flow.
## Scope
### akkounts
- Issue a `refresh_token` alongside the access token in the PKCE token exchange (`POST /rs/oauth/token`).
- Support `grant_type=refresh_token` at the token endpoint: validate the refresh token, rotate the access token (update Redis `authorizations:<cn>:<token>`), and return the new token.
- Keep the grant alive until the user-selected authorization expiry (`RemoteStorageAuthorization#expire_at`), independent of the access-token TTL.
- Store/rotate refresh tokens securely (hashed at rest; rotation + reuse detection per RFC 9700).
- Decide the access-token TTL and how Liquor Cabinet stays consistent during rotation.
### remoteStorage.js (separate repo)
Automatic refresh on `401` currently exists **only in the Dropbox backend** (`src/dropbox.ts`, guarded by `this.refreshToken`). The generic remoteStorage backend only emits `UnauthorizedError` (`src/remotestorage.ts`).
- Mirror the Dropbox refresh path in the generic backend so apps benefit automatically.
- Until that ships, refresh tokens would be inert for the main client, which is why this was deferred.
## References
- #254 (PKCE)
- RFC 6749 §1.5 / §6 (refresh tokens)
- RFC 9700 (OAuth 2.0 Security BCP) — refresh token rotation and reuse detection
- draft-dejong-remotestorage-27 §10/§10.1 (defines bearer tokens, no refresh)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follow-up to #254 (PKCE for RS OAuth). We deliberately deferred this to keep #254 focused.
Goal
Decouple authorization/grant validity from access-token validity: short-lived access tokens that renew automatically, while the grant stays valid for the user-selected period (never / 1 month / 1 day) and remains revocable per device.
Today, with the implicit and PKCE flows, the access token lives exactly as long as the authorization. When it expires, the remoteStorage client gets a
401, emits anUnauthorizedError, and the user must reconnect through the OAuth dialog (which mints a new per-device token).PKCE itself does not refresh anything — RFC 7636 only secures the authorization-code exchange. Refresh tokens are a separate OAuth mechanism, and remoteStorage 1.0 does not define a refresh flow.
Scope
akkounts
refresh_tokenalongside the access token in the PKCE token exchange (POST /rs/oauth/token).grant_type=refresh_tokenat the token endpoint: validate the refresh token, rotate the access token (update Redisauthorizations:<cn>:<token>), and return the new token.RemoteStorageAuthorization#expire_at), independent of the access-token TTL.remoteStorage.js (separate repo)
Automatic refresh on
401currently exists only in the Dropbox backend (src/dropbox.ts, guarded bythis.refreshToken). The generic remoteStorage backend only emitsUnauthorizedError(src/remotestorage.ts).References