Repository navigation
login: default to auth.entire.io and follow its regional handoff - #1945
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Updates entire login to default to the apex auth host (https://auth.entire.io) and correctly complete OAuth flows against the regional core that actually issues tokens/codes, while enforcing a strict issuer-delegation policy to prevent hostile handoffs.
Changes:
- Default login server switched to
https://auth.entire.io(dispatcher), with device and browser flows retargeting token exchange/polling to the regional issuer. - Added issuer adoption + validation logic (
adoptIssuer, enhancedissMatches) to allow only exact-origin or strict-HTTPS-subdomain delegation on the same port. - Expanded unit + integration-style tests to cover apex→regional redirects, hostile issuer attempts, and success messaging/persistence behavior.
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates local-dev guidance to reflect the new default dispatcher host. |
| go.mod | Bumps github.com/entireio/auth-go to a newer pseudo-version needed for dispatch support. |
| go.sum | Updates module checksums for the auth-go bump. |
| docs/architecture/upstream-host-resolution.md | Documents apex-dispatch vs regional-issuer behavior and the CLI’s issuer trust rules. |
| cmd/entire/cli/api/base_url.go | Changes DefaultAuthBaseURL to https://auth.entire.io and documents dispatcher semantics. |
| cmd/entire/cli/login.go | Implements issuer adoption/retargeting for device + browser flows and validates delegated issuers. |
| cmd/entire/cli/login_validate_test.go | Updates login-server parsing tests for the new default host. |
| cmd/entire/cli/login_test.go | Extends mocks/fakes to support new issuer-retargeting behavior. |
| cmd/entire/cli/login_issuer_test.go | Adds focused tests for issuer matching/adoption, retargeting, and success output. |
| cmd/entire/cli/auth/provider.go | Updates comments to describe fixed-path behavior and apex dispatch constraints. |
| cmd/entire/cli/auth/client.go | Adds token-issuer override support for device flow and exposes callback iss for browser flow. |
| cmd/entire/cli/auth/client_dispatch_test.go | Adds httptest-based end-to-end coverage for apex dispatch behavior in both flows. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
toothbrush
added a commit
that referenced
this pull request
Aug 14, 2026
… can't apply issMatches always said "expected <origin> or a subdomain of it", but isDelegatedIssuer only ever accepts a subdomain when both sides are https. Against a plaintext dev/loopback login server that wording points the reader at a host that would be rejected too. Addresses #1945 (comment) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Entire-Checkpoint: 01M0017AGHRB873EM61G0N84AK
toothbrush
force-pushed
the
glittery-gliding-pretzel
branch
from
August 14, 2026 11:52
3a24a0b to
47cfb2f
Compare
…al handoff `entire login --server` now defaults to https://auth.entire.io. That host is a dispatcher, not an issuer: it redirects /authorize and /device_authorization to the caller's regional core and serves no token endpoint, no discovery document, and no JWKS. Tokens are always minted by a region with iss/aud set to that region's host, so the CLI has to discover the region mid-login and send the token request there. - Browser flow: the region appends the RFC 9207 `iss` parameter to the loopback redirect; runBrowserLogin reads it and redeems the code at that host. Posting the exchange to the apex would 404. - Device flow: the apex 307s POST /device_authorization to the region (307 preserves method and body); DeviceAuthStart.ResponseOrigin reports which host answered and the token poll follows it. Both handoffs — and the iss claim on the returned token — are gated by one rule in issMatches: the dialled origin itself, or a strict subdomain of it over https on the same port. That accepts auth.entire.io -> us.auth.entire.io and rejects auth.entire.io.evil.com, siblings, port changes, and plaintext downgrades. A hostile handoff aborts before the authorization code or device code is sent anywhere. Nothing downstream changes: RecordLoginContext still keys the context and keychain slot on the token's own iss, and refresh + RFC 8693 exchange still target that persisted CoreURL. Login now prints the issuing region when it differs from the host the user dialled, since that is what later calls hit. NOTE: go.mod carries a temporary local `replace` for github.com/entireio/auth-go. The apex support needs auth-go changes (authcode Flow.Issuer / SetTokenBaseURL, deviceflow DeviceCode.ResponseOrigin / Client.TokenBaseURL); that must be released and the replace dropped before this can merge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the temporary local replace directive with a pseudo-version pin on entireio/auth-go#20. Swap for a tagged v0.5.3 once released. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 01KZQMJ1BJQDX30J4QJNSKVZT4
… can't apply issMatches always said "expected <origin> or a subdomain of it", but isDelegatedIssuer only ever accepts a subdomain when both sides are https. Against a plaintext dev/loopback login server that wording points the reader at a host that would be rejected too. Addresses #1945 (comment) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Entire-Checkpoint: 01M0017AGHRB873EM61G0N84AK
main's interactive URL prompt (#1961) replaced runLogin/runBrowserLogin's browserOpenFunc parameter with a loginURLInteractor. The issuer tests now build one via newTestLoginURLInteractor(); with no scripted actions its readAction blocks until the flow completes, which is what these tests want. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Entire-Checkpoint: 01M0067HPPRSVVQB2TAH6K8YN5
Picks up entireio/auth-go#20 toolchain bump on top of the regional-dispatch hooks. auth-go now requires Go >= 1.26.6, so `go get` raised this module's go directive too; mise.toml follows it per the comment there. The bump clears six stdlib advisories (net/url, crypto/tls x2, net/http x2, encoding/asn1) that the CLI shared with auth-go. Still a pseudo-version — swap to tagged v0.5.3 once released. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Entire-Checkpoint: 01M006E3KSMP7GXWZ2SBH9Y7TQ
toothbrush
force-pushed
the
glittery-gliding-pretzel
branch
from
August 14, 2026 13:21
47cfb2f to
4108ef9
Compare
Three findings from trail 1006, two fixed and one answered in a comment. Transport-guard asymmetry (finding 3): BrowserAuthFlow.UseTokenIssuer delegated straight to auth-go's SetTokenBaseURL, which honours AllowInsecureHTTP for any host, while the device flow's Client.UseTokenIssuer refuses to let --insecure-http-auth extend to a runtime-named non-loopback host. Unreachable today because adoptIssuer demands https on both sides, but the two paths must not disagree about policy or loosening adoptIssuer would loosen only one. The browser shim now applies the same rule. Unasserted test claim (finding 4): TestPersistLogin_DispatchedLoginNamesTheRegion said it verified the region is recorded as the context's CoreURL, but checked only the stdout line. It now asserts the persisted CoreURL, which is the half that makes refresh work. Token iss validated against the dialled apex, not the adopted region (finding 2): left as-is, deliberately, and documented on persistLogin. The suggested tightening — require iss == the adopted issuer — would break correct cross-region logins: the apex geo-routes POST /device_authorization, so the region that answers a handoff is not necessarily the region that mints, and the dialled apex is the only origin both are guaranteed to sit under. Pinning the token request answers "where may this code go?"; the iss check answers "is this issuer acceptable at all?". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Entire-Checkpoint: 01M00B533P53MDR7RHFYSSM3R8
Reverses the reasoning in the previous commit, which declined trail finding 2 on the grounds that the minting region may legitimately differ from the region that answered the handoff. It may not: iss names the *signer*, and a verifier resolves JWKS from it, so a token can only truthfully claim the region that actually minted it — which is the region the flow was handed off to. A token arriving from us.auth.entire.io while claiming eu.auth.entire.io is misconfiguration, and validating against the dialled apex alone waved it through because both sit under it, leaving a context whose every later refresh would fail against a region that never issued the token. persistLogin now takes the adopted issuer alongside the dialled host and validates iss against the former when a handoff occurred, the latter when it did not. The success line still compares against the dialled host, so it keeps naming the region only when it differs from what the user asked for. Cross-region minting stays supported and needs no leniency here: the apex geo-routes POST /device_authorization, so an AU-homed account can be served and signed by EU. That is expressed by iss=EU plus home_jurisdiction=AU, not by EU claiming to be AU. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Entire-Checkpoint: 01M00BPKYR96N5K525135K1VHK
Soph
approved these changes
Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
https://entire.io/gh/entireio/cli/trails/1006
Why
https://auth.entire.io (entire-core global mode) now dispatches logins to the caller's regional core (https://github.com/entirehq/entiredb/pull/3135): identify-first 302 on
/authorize, geo 307 on/device_authorization. That removes the main need for--server— but the apex serves no token endpoint, so the CLI must finish each flow against the region that actually minted the code.What
entire logindefaults tohttps://auth.entire.io(--serverstays for special cases).issfrom the loopback callback and exchanges the code at that regional host; device flow polls the origin that served the 307'd response.issacceptance: exactly the dialled origin, or a strict https subdomain of it on the same port (us.auth.entire.iounderauth.entire.io;auth.entire.io.evil.com,xauth.entire.io, scheme/port downgrades all rejected). The mismatch error only offers the subdomain shape when the dialled origin is https, since a plaintext dev/loopback server can never delegate.v0.5.3-0.20260814125012-86c083be00da) — swap to tagged v0.5.3 once released.go.mod+mise.toml). Required: that auth-go commit raises its own minimum to 1.26.6. It also clears six stdlib advisories this CLI shares with auth-go — GO-2026-6218 (net/url), GO-2026-6090 + GO-2026-5856 (crypto/tls), GO-2026-6089 + GO-2026-5026 (net/http), GO-2026-5972 (encoding/asn1).Verification
mise run lint: 0 issues;go test ./cmd/entire/cli/ ./cmd/entire/cli/auth/ ./cmd/entire/cli/api/pass on go1.26.6.login_issuer_test.go(issuer-rule table incl. hostile cases, plus the error-wording rule),auth/client_dispatch_test.go(httptest apex 307→regional device flow; loopback callback withiss→ regional exchange; apex 404s everything else so a missed handoff fails loudly).entire login --deviceexits withstart login: start device auth: status 404: 404 page not found.flow.Waitonto its own goroutine. Audited every exit path inwaitForLoginURLResult: each returns via awaitChreceive, so the channel supplies the happens-before edge for the subsequentflow.Issuer()read. Device flow setsTokenBaseURLbefore the polling goroutine is spawned.entire-cliclient registration on non-us regions.🤖 Generated with Claude Code
Note
High Risk
Changes authentication defaults, token endpoint targeting, and issuer delegation policy—security-critical paths with new subdomain trust rules that must not be bypassed by hostile redirects or callback
issvalues.Overview
entire loginnow defaults tohttps://auth.entire.ioinstead of a regional host (us.auth.entire.io). The apex only redirects OAuth entry points and has no token endpoint, so the CLI must finish login against the regional core that actually mints tokens.Device flow: after
/device_authorization, the CLI usesResponseOriginandUseTokenIssuerso token polls hit the region that answered the redirect, not the apex.Browser flow: it reads RFC 9207
isson the loopback callback and redeems the authorization code at that regional host.Trust rules:
adoptIssuer/ expandedissMatchesallow the dialled apex or a strict HTTPS subdomain on the same port (e.g.us.auth.entire.iounderauth.entire.io); lookalike domains, siblings, and HTTP downgrades are rejected. The same rule validates JWTissbefore persistence. Success output names the real issuer when it differs from--server.auth-go is pinned to a newer pre-release for
ResponseOriginand token-base URL overrides. README and upstream-host-resolution docs describe the apex-vs-region model; httptest coverage exercises apex→regional device and browser paths.Reviewed by Cursor Bugbot for commit 3a24a0b. Configure here.