Skip to content

GitHub sign-in only where it works - #456

Merged
nambok merged 1 commit into
mainfrom
github-sign-in-only-when-it-works
Nov 3, 2026
Merged

nambok merged 1 commit into
mainfrom
github-sign-in-only-when-it-works

Conversation

@nambok

@nambok nambok commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

On a self-hosted install that uses CoderHelm's GitHub App (hybrid), the install has no GitHub OAuth client of its own, yet the sign-in page offered Continue with GitHub and GET /auth/github sent people to github.com/login/oauth/authorize?client_id=&..., which GitHub answers with a 404.

The server now decides which sign-in methods work and says so; GitHub sign-in is available only with the install's own client id and secret. Signing in through CoderHelm's hosted side stays off on purpose: the hybrid GitHub flow (/hybrid/github/setup) only proves an installation is yours for linking, and using it for sign-in would let the hosted side vouch for people on the install (docs/self-host/hybrid.md already lists "Sign in with GitHub: no" for this reason).

Changes

  • GET /auth/methods (public, no session, outside the sign-in attempts' rate limit): { "password": true, "google": <hosted only>, "github": <own client id and secret stored> }.
  • GET /auth/github and GET /auth/github/callback with no client (or half of one) go back to the sign-in screen with ?signin_error=not_set_up&provider=github, never to GitHub with an empty client_id.
  • New setup check github_sign_in (Settings, Setup): warns when the install's own GitHub App has no OAuth client stored, or only the id or only the secret; skip on an install that uses CoderHelm's GitHub App. Never blocks an update.
  • Docs: check-your-install.md lists the new key; sign-in.md says when the sign-in page offers GitHub.
  • No change to any sign-in check (2FA, team rules, invites); the callback's flow is untouched when a client exists.

Verification

  • cargo fmt --all --check, cargo clippy -p gateway --all-targets -- -D warnings, cargo test -p gateway (681 passed).
  • New unit tests: github_sign_in_needs_both_halves_of_the_client, the_methods_list_has_only_what_works, github_with_no_client_goes_back_to_sign_in_not_to_github (302 to the sign-in screen, no github.com), github_sign_in_flags_a_missing_client_and_never_blocks_an_update.
  • The dashboard side (reads /auth/methods, hides dead buttons) is a separate PR in CoderHelm/coderhelm.

The sign-in page offered Continue with GitHub on every install, and an
install with no GitHub OAuth client of its own (hybrid, on CoderHelm's
app) sent people to GitHub with an empty client_id, which 404s.

- GET /auth/methods (public, outside the sign-in rate limit) says which
  sign-in methods work: password always, Google on the hosted side only,
  GitHub only with the install's own client id and secret.
- GET /auth/github and its callback with no client go back to the
  sign-in screen with signin_error=not_set_up instead of to GitHub.
- New github_sign_in setup check: warns when the install's own app has
  no client (or half of one), skip on CoderHelm's app; never blocks an
  update.
- Hybrid sign-in through CoderHelm stays off: it would let the hosted
  side vouch for people on the install.
@nambok
nambok merged commit 2efad10 into main Nov 3, 2026
10 checks passed
@nambok
nambok deleted the github-sign-in-only-when-it-works branch November 3, 2026 20:12
nambok added a commit that referenced this pull request Nov 4, 2026
)

A hybrid install has no GitHub OAuth client of its own, so #456 hid
Continue with GitHub there. People need it to get in, so it now goes
through CoderHelm's app, with the install making every decision.

- The install makes a state and a PKCE verifier, seals them in a
  __Host- cookie with its own key, and asks the hosted side (signed v2)
  to start a flow for its own callback, /auth/github/hybrid-callback.
  The hosted side accepts only that path on the install's verified
  CloudFront or CoderHelm address.
- GitHub returns to the already registered hosted callback
  (/auth/github/callback/hybrid, state=hsi_...). The hosted side takes
  the flow once, checks the install again and forwards the browser with
  the code; it keeps only the code's hash, for 5 minutes.
- The install checks state and flow against its cookie, then asks the
  hosted side (signed) to exchange the code with the verifier; the
  hosted side checks the install, the code hash and PKCE, and GitHub
  checks the verifier too. The token is answered, never stored or
  logged.
- The install reads the GitHub account from GitHub itself and runs the
  same sign-in as its own client would (github_sign_in_with_token:
  members, invites, allowed domains, no sign-up, two-factor), links no
  installations, then has the hosted side revoke the token at GitHub.
- /auth/methods says github: true for a registered hybrid install; the
  github_sign_in check passes there and warns until it is registered.
- The Settings card for Sign in with GitHub says what passes through
  CoderHelm and what stays with the install (new mode: included).
- Docs: hybrid.md has the flow and what CoderHelm sees and can do;
  sign-in.md and check-your-install.md follow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant