fj auth login --fjord fails out of the box: DEFAULT_PLATFORM_URL points at the Cloudflare Access-protected pages.dev origin #250

Closed
opened 2026-08-13 18:20:15 +00:00 by stephen · 0 comments
Owner

Two independent problems make Fjord Account sign-in unusable without knowing the workaround. Both hit on the current release (0.4.1) on a headless Linux box.

1. The default platform URL is the pages.dev origin, which is behind Cloudflare Access

src/fjord/mod.rs:24:

pub const DEFAULT_PLATFORM_URL: &str = "https://forgejo-site.pages.dev";

That host is protected by Cloudflare Access, so the device-authorization request gets an HTML sign-in page rather than JSON:

error: starting device-flow sign-in
  caused by: decoding device-authorization response: <!DOCTYPE html>
    <title>Sign in ・ Cloudflare Access</title>
  caused by: expected value at line 1 column 1

Passing the real production URL works immediately:

fj auth login --fjord --platform-url https://fjord.sh

The device flow then starts correctly, prints the code and QR, and points at https://fjord.sh/device.

Suggested fix: default to https://fjord.sh. A deployment-preview origin should not be the fallback for every user, and an Access-protected one can never work for a non-interactive client. Worth also detecting a non-JSON content type and saying "the platform URL is not serving the API, it returned an HTML page, check --platform-url" rather than surfacing a JSON decode error, which sends you looking at the wrong layer.

2. An exported FJ_TOKEN blocks --fjord entirely

--token is declared with env = "FJ_TOKEN", so an exported token is treated as if it had been typed:

$ fj auth login --fjord
error: the argument '--fjord' cannot be used with '--token <TOKEN>'

The workaround is env -u FJ_TOKEN fj auth login --fjord. Note FJ_TOKEN= fj auth login --fjord is not enough, since an empty-but-set variable still reads as present.

This matters more than a normal flag conflict because fj#147's own guidance is to export FJ_TOKEN from the shell profile to survive a locked keychain. Following the documented setup therefore makes --fjord unreachable in every shell.

Suggested fix: only conflict when --token came from the command line. src/cli/auth_login.rs:762 already distinguishes an env-provided token from an explicit one, so the information exists and simply is not used for the conflict rule. An env token should be ignored in --fjord mode, or at most warned about.

src/auth/mod.rs:96: "Look up the token for host: first FJ_TOKEN, then keychain, then file."

So FJ_TOKEN is presented to whatever host is targeted, and shadows any per-host credential. Concretely, fj api --host commons.fjord.host sends the rasterhub.com PAT to commons and gets a 401, and fj auth status --host commons.fjord.host reports rasterhub.com regardless. Signing into a second host does not take effect while the variable is exported.

Both hosts here are ours so the exposure is small, but a credential for one forge being transmitted to another because of an environment variable is worth closing. Scoping it, for example FJ_TOKEN_<HOST> or honouring it only for the current host, would fix the shadowing and the surprise together.

Two independent problems make Fjord Account sign-in unusable without knowing the workaround. Both hit on the current release (0.4.1) on a headless Linux box. ## 1. The default platform URL is the pages.dev origin, which is behind Cloudflare Access `src/fjord/mod.rs:24`: ```rust pub const DEFAULT_PLATFORM_URL: &str = "https://forgejo-site.pages.dev"; ``` That host is protected by Cloudflare Access, so the device-authorization request gets an HTML sign-in page rather than JSON: ``` error: starting device-flow sign-in caused by: decoding device-authorization response: <!DOCTYPE html> <title>Sign in ・ Cloudflare Access</title> caused by: expected value at line 1 column 1 ``` Passing the real production URL works immediately: ``` fj auth login --fjord --platform-url https://fjord.sh ``` The device flow then starts correctly, prints the code and QR, and points at `https://fjord.sh/device`. **Suggested fix:** default to `https://fjord.sh`. A deployment-preview origin should not be the fallback for every user, and an Access-protected one can never work for a non-interactive client. Worth also detecting a non-JSON content type and saying "the platform URL is not serving the API, it returned an HTML page, check --platform-url" rather than surfacing a JSON decode error, which sends you looking at the wrong layer. ## 2. An exported `FJ_TOKEN` blocks `--fjord` entirely `--token` is declared with `env = "FJ_TOKEN"`, so an exported token is treated as if it had been typed: ``` $ fj auth login --fjord error: the argument '--fjord' cannot be used with '--token <TOKEN>' ``` The workaround is `env -u FJ_TOKEN fj auth login --fjord`. Note `FJ_TOKEN= fj auth login --fjord` is not enough, since an empty-but-set variable still reads as present. This matters more than a normal flag conflict because fj#147's own guidance is to export `FJ_TOKEN` from the shell profile to survive a locked keychain. Following the documented setup therefore makes `--fjord` unreachable in every shell. **Suggested fix:** only conflict when `--token` came from the command line. `src/cli/auth_login.rs:762` already distinguishes an env-provided token from an explicit one, so the information exists and simply is not used for the conflict rule. An env token should be ignored in `--fjord` mode, or at most warned about. ## 3. Related, the same env token is host-agnostic `src/auth/mod.rs:96`: "Look up the token for `host`: first `FJ_TOKEN`, then keychain, then file." So `FJ_TOKEN` is presented to whatever host is targeted, and shadows any per-host credential. Concretely, `fj api --host commons.fjord.host` sends the rasterhub.com PAT to commons and gets a 401, and `fj auth status --host commons.fjord.host` reports rasterhub.com regardless. Signing into a second host does not take effect while the variable is exported. Both hosts here are ours so the exposure is small, but a credential for one forge being transmitted to another because of an environment variable is worth closing. Scoping it, for example `FJ_TOKEN_<HOST>` or honouring it only for the current host, would fix the shadowing and the surprise together.
Sign in to join this conversation.
No milestone
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
rasterstate/fj#250
No description provided.