Skip to content

Token / gh-cli auth mode: dashboard data endpoints return 401 (needsAuth) despite /api/auth/status being authenticated #24

Description

@DutchmanNL

Summary

In GH_AUTH_MODE=token (and gh-cli) mode, /api/auth/status reports the token as authenticated, but every dashboard/data endpoint returns 401 {"ok":false,"error":"authentication required","needsAuth":true}. The UI then shows "Connect an account / GITHUB_TOKEN is not available", even though the token is valid and present.

Symptoms

  • GET /api/auth/status{"authenticated":true,"login":"…","mode":"token"}
  • GET /api/repos (and /api/issues, /api/pulls, notifications, CI health) → 401 {"ok":false,"error":"authentication required","needsAuth":true}
  • GET /api/accounts{"accounts":[],"activeId":null} (empty)

Root cause

The status endpoint and the data layer resolve auth through two different paths, and only the status path understands env / gh-cli tokens:

  • /api/auth/statusgetProviderStatus() in src/server/authProvider.ts. In token mode it calls loadEnvToken(), validates the env token, and returns authenticated:true. ✅
  • Data endpoints → src/server/dashboardData.ts resolveActive() (~L64) → getActive() in src/server/accountStore.ts. getActive() only returns accounts from the on-disk account store. In pure token/gh-cli mode nothing ever writes to that store, so it returns nullauthFail()401 needsAuth on every data endpoint.
  • src/server/accountStore.ts doInit() seeds the store only from accounts.json or a legacy auth.json — there is no code path that seeds it from GITHUB_TOKEN / the gh CLI. So env-token and gh-cli modes leave the store permanently empty.

Notably the infrastructure for a fix already exists: accountStore.getActive() explicitly prefers an ephemeral env-based account (if (s.ephemeral.length > 0) return s.ephemeral[0]) and add() supports ephemeral:true accounts — but no code path ever creates that ephemeral account in token/gh-cli mode.

Reproduction

# empty account store (no ~/.gitdeck/accounts.json, no legacy auth.json)
GH_AUTH_MODE=token GITHUB_TOKEN=<a PAT with repo + read:org> npm run api

curl -s localhost:8765/api/auth/status   # {"authenticated":true,...}
curl -s localhost:8765/api/repos          # 401 {"ok":false,"error":"authentication required","needsAuth":true}

gh-cli mode (GH_AUTH_MODE=gh-cli with gh auth login done) has the same gap: the status endpoint authenticates but the data endpoints 401.

Suggested fix

When the auth mode is token/gh-cli, register an ephemeral account synthesised from the external credential (providerKind:"github", providerConfigId:"github.com", accessToken = env / gh token, ephemeral:true) so getActive() resolves it and the data endpoints use it. This reuses the ephemeral-account support already present in accountStore.

I have a fix + regression tests ready and will open a PR referencing this issue.

Secondary note (not necessarily a bug)

listOwners in src/server/providers/github.ts (~L265) enumerates owners via /user/orgs. Fine-grained PATs return [] there, so only personal repos are listed — a classic read:org PAT is required to see org repos. This is GitHub token behaviour rather than a GitDeck bug, but it may be worth documenting the classic-token requirement (or allowing explicit orgs/owners to be configured) so fine-grained-PAT users aren't surprised by missing org repos.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions