Idea: forge.py login on a second machine signs the first one out (one OAuth grant per user); add a token sign-in #435

Open
opened 2026-11-14 13:52:46 +00:00 by mooki · 0 comments
Member

The idea

@HumanBean: signing in with python -I scripts/forge.py login on a second machine signs you out on the first, within
about an hour.

Forgejo keeps one OAuth grant per user per application, and every machine signs in through the same app
(GIT_CLIENT_ID in scripts/magicbean_login.py). In Forgejo's routers/web/auth/oauth.go:

  • a sign-in reuses the user's existing grant for the app (GetGrantByUserID, line 617);
  • every token issued, at sign-in or at a refresh, increments the grant's counter (lines 161-162, when
    InvalidateRefreshTokens is on);
  • a refresh token carrying an older count is refused with unauthorized_client, "token was already used" (lines
    827-831).

git.magicbean.dev has InvalidateRefreshTokens on. So when machine A signs in or renews, machine B's refresh token goes
stale. B keeps working until its access token runs out (expires_in, about an hour). Then its next renewal fails:

the git.magicbean.dev sign-in could not be renewed (POST https://git.magicbean.dev/login/oauth/access_token: HTTP 400
{"error":"unauthorized_client","error_description":"token was already used"}): sign in again

Signing in again on B does the same to A. The _SessionLock in magicbean_login.py fixed this race between two
processes on one machine, but it can't help across machines. Seen today between a Linux PC and a Mac on the same account.

Proposed fix (a PR follows): python -I scripts/forge.py login --token-stdin takes a Forgejo personal access token
(Settings → Applications) from standard input. It is saved as the sign-in with no refresh token, so it doesn't use the
OAuth grant at all. A second machine uses a token, and the main machine keeps the Discord sign-in. docs/forge.md gets a
short "Two machines" section.

The alternatives are for a server admin, so they're your call:

  • turn off [oauth2] INVALIDATE_REFRESH_TOKENS, which weakens refresh-token reuse detection for everyone;
  • register a second OAuth application for a second machine.

Anything else

Related: #420 (found while setting up the macOS port on a second machine).

### The idea @HumanBean: signing in with `python -I scripts/forge.py login` on a second machine signs you out on the first, within about an hour. Forgejo keeps **one OAuth grant per user per application**, and every machine signs in through the same app (`GIT_CLIENT_ID` in `scripts/magicbean_login.py`). In Forgejo's `routers/web/auth/oauth.go`: - a sign-in reuses the user's existing grant for the app (`GetGrantByUserID`, line 617); - every token issued, at sign-in or at a refresh, increments the grant's counter (lines 161-162, when `InvalidateRefreshTokens` is on); - a refresh token carrying an older count is refused with `unauthorized_client`, "token was already used" (lines 827-831). git.magicbean.dev has `InvalidateRefreshTokens` on. So when machine A signs in or renews, machine B's refresh token goes stale. B keeps working until its access token runs out (`expires_in`, about an hour). Then its next renewal fails: ``` the git.magicbean.dev sign-in could not be renewed (POST https://git.magicbean.dev/login/oauth/access_token: HTTP 400 {"error":"unauthorized_client","error_description":"token was already used"}): sign in again ``` Signing in again on B does the same to A. The `_SessionLock` in `magicbean_login.py` fixed this race between two processes on one machine, but it can't help across machines. Seen today between a Linux PC and a Mac on the same account. **Proposed fix (a PR follows):** `python -I scripts/forge.py login --token-stdin` takes a Forgejo personal access token (Settings → Applications) from standard input. It is saved as the sign-in with no refresh token, so it doesn't use the OAuth grant at all. A second machine uses a token, and the main machine keeps the Discord sign-in. `docs/forge.md` gets a short "Two machines" section. The alternatives are for a server admin, so they're your call: - turn off `[oauth2] INVALIDATE_REFRESH_TOKENS`, which weakens refresh-token reuse detection for everyone; - register a second OAuth application for a second machine. ### Anything else Related: #420 (found while setting up the macOS port on a second machine).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot#435
No description provided.