~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

knotless login's page fits in the browser's Referer again

Merged
Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:cli/short-login-url

What changes

The login's space scopes name their type alone. oauth::SCOPE asks for space:dev.knotless.space?authority=*&manage=… and the same of dev.knotless.orgSpace, without a collection= for each collection the type's lexicon lists. The PDS resolves each type's lexicon and grants those collections as it issues the token (expandSpaceCollections in the spaces alpha), so the grant is the same.

The methods called are one scope. rpc?lxm=dev.knotless.pushRefs&lxm=…&aud=* in place of an rpc:<method>?aud=* for each. The permission syntax allows several lxm values in one scope; @atproto/oauth-scopes 0.5.14 parses it and matches only the methods it names.

Older logins stay current. behind() takes a login asked for the old, spelled-out form (SPELLED_OUT) as holding SCOPE, so no one, on the command line or the pages, is asked to log in again.

The gateway's grant (gateway::SCOPE) goes through a hosted client ID and is left as it is.

Why

A user logging in with knotless login on bsky.social got {"error":"invalid_request","error_description":"Invalid referer …"} on approving. The loopback client's ID (http://localhost?redirect_uri=…&scope=…) carries the whole scope, encoded twice in the authorize URL, which had reached 4,624 bytes. Chrome and Firefox cut a Referer longer than 4,096 bytes to its origin, and the reference PDS refuses /oauth/authorize/accept and sign-in unless the Referer is the authorize page with its client_id and request_uri. The spelled-out space scopes from the pull that named knotless's own space types (e4810f7e, about 1,000 bytes of the URL) took it over the limit; the ~55 rpc scopes were another 2,300. The pages and MCP log in under a hosted client ID and were not affected.

Shortening the space scopes alone left the URL a few methods short of the limit again; folding the rpc scopes gives it room. A hosted client ID for the command line, as the pages have, would keep the URL short however the scope grows, and is left for later.

How it was checked

login_page_url_fits_a_referer builds the authorize URL as authorize does, on bsky.social, and fails at 4,096 bytes or more. client checks the new form, and sessions_behind_what_is_asked that a spelled-out login is current for SCOPE and not for the gateway's. Against the CI-pinned alpha (11c5d98c), a bare typed space scope is expanded to its lexicon's collections at issue. The Rust tests and e2e log in over OAuth against that PDS, so CI runs real logins through the new scope.

Shortcomings

Not tried in a browser against bsky.social itself before landing: the upstream parser accepts the multi-lxm scope, but bsky.social's PDS version is not known here. A bare space scope on a PDS without spaces is dropped, as before.

Approved

This shortens the loopback login scope so the authorize URL stays under the 4,096-byte Referer limit. Space scopes name their type alone. The ~55 rpc: scopes become one rpc?lxm=…&aud=*. behind() treats a login made with the old spelled-out scope as current for SCOPE, so existing logins aren't prompted again.

I found nothing that must change. The behind rewrite keeps the old semantics: no OAuth session is never behind, and an unknown scope is behind. The spelled-out equivalence applies only when asked == SCOPE, so the gateway grant is unaffected. The new URL-length test and the updated client and behind tests cover the change. A change file is included. The test, check and e2e runs were still queued when I looked, so I didn't see them pass.

Two risks you already name:

  • The multi-lxm scope is untried on bsky.social's PDS. If that PDS doesn't parse it, it may drop all rpc access, which would break login-dependent calls without any error at login. Try it there before relying on it.
  • The URL has only modest headroom, as the body says. The hosted client ID is the lasting fix.
Merged as 934cebc