This PR is not complete (missing items detailed below), but I am submitting it already as a draft to get some early feedback. Please check the description below before checking code - I would really appreciate feedback on the overall design which is included in the description. But comments on the partially complete code are of course welcome as well.
Introduction
This PR contains an overhaul of Lemmy authentication. It introduces three new authentication tokens: access tokens, refresh tokens, and api tokens (more details below).
The changes are intended to be backwards compatible - the existing /login endpoint will become deprecated but will remain operational until we are ready to remove it in a future version.
What is wrong with our current authentication?
- Auth tokens never expire: https://github.com/LemmyNet/lemmy/issues/3364
- Auth sessions can't be revoked by users
- There is no support for httpOnly cookie based auth: https://github.com/LemmyNet/lemmy-ui/issues/1252
- There is no support for api token based auth - all 3rd party apps require user passwords
- All auth tokens have full access to everything, their scope can't be limited
This PR contains intends to solve all these issues.
Proposed solution
This PR proposes to replace the existing auth token with 3 new types of tokens:
Access token
This token can be acquired with either a refresh token or an API token.
The new access token is intended to be a backwards compatible drop-in replacement for the existing auth token, with a few key differences:
- It expires within 5 minutes (so even if it leaks, it can only be abused within 5 minutes of the leak)
- It contains a
method
claim, which can be used later to limit certain activities to specific methods (for example, disallow password changes if the access token was obtained via an API token)
Refresh token
This token can be acquired using username + password (+ 2fa).
It lives in a secure httpOnly cookie (can't be read from browser js), which is limited only to the /api/v3/get_access_token path.
This is intended only for trusted web interfaces (such as lemmy-ui) and can be used to create access tokens with full access to the user. Each refresh token can be considered a separate "session". Each token records its last use time, as well as last use ip address - these values can be displayed to users in some new security UI so they get an overview of their active sessions. Each refresh token expires 2 weeks after it was last used, or when revoked manually by a user.
API token
This token must be manually created by users with a specific label and expiry date.
This is intended for 3rd party apps to avoid users from entering their passwords directly into untrusted code. The api token can be used similarly to refresh tokens to request access tokens, but the created access tokens would have limited access. Each API token will also record their last use time as well as last use ip address. API tokens expire after their user defined expiry date, or when revoked manually.
To summarize the general flow:
- Acquire either a refresh token (if trusted web ui) or an API token (if 3rd party app)
- Request access token using the token from step 1
- Make all API requests with access token from step 2
- If access token is close to expiry (or last request failed due to token), get a new access token (and retry last request)
- If getting access token fails due to a token error, assume the (refresh or api) token has expired and go back to step 1
Rollout plan
- Release the new logic in a minor Lemmy version
- Add a migration guide to release notes to allow app developers to migrate to the new APIs
- Update Lemmy-ui to use the new endpoints
- After some time has passed, remove the old /login endpoint in a backwards-incompatible Lemmy update
TODO in this PR
- Add refresh token list & revoke endpoints
- Add api token create & list & revoke endpoints
- Disallow some actions (new api token creation + password change + reading user e-mail?) when access token method is
Api
- Add some tests
TODO in future PRs
- Switch lemmy-ui to use new authentication
- Add security page to lemmy-ui, where users can see and revoke their sessions (refresh tokens), as well as see/revoke/create API tokens
- Add method for 3rd party apps to redirect users to an API token creation page (with a potential return_url to automatically get back to the app with the created token)