Skip to content

Fix CLI token refresh by preserving OAuth port across sessions - #64

Merged
disnet merged 3 commits into
disnet:mainfrom
tijs:fix/cli-token-refresh
Feb 28, 2026
Merged

disnet merged 3 commits into
disnet:mainfrom
tijs:fix/cli-token-refresh

Conversation

@tijs

@tijs tijs commented Feb 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Store the OAuth loopback port used during sb login in session.json
  • Reuse that port when creating the NodeOAuthClient for session restoration, so the client_id stays consistent and token refresh works after the access token expires (~1 hour)
  • Improve error message when session expires to show the user's handle and suggest re-login

Fixes #63

Changes

cli/src/lib/config.ts — Add optional oauthPort field to AuthInfo

cli/src/lib/auth.ts —

  • login(): Save the port in auth info
  • getAgent(): Use stored port (falls back to 0 for existing sessions)
  • requireAgent(): Show "Session expired" with handle instead of generic "Not logged in"

Test plan

  • All 66 existing tests pass
  • Type-checking passes
  • Manual: sb login, wait >1 hour, run sb cards — should work without re-login
  • Manual: Verify ~/.config/skyboard/session.json now contains oauthPort
  • Manual: Existing sessions (without oauthPort) gracefully fall back to port 0

The OAuth client_id for loopback clients includes the redirect URI port.
During login, a random free port is used (e.g. 54321), but when restoring
sessions, port 0 was hardcoded. This client_id mismatch caused the PDS to
reject token refresh requests after the access token expired (~1 hour),
making users appear logged out.

Now the port from login is stored in session.json and reused for session
restoration, keeping the client_id consistent so refresh tokens work.

Also improves the error message when sessions expire to show the user's
handle and suggest re-login instead of the generic "not logged in" message.
Pass authInfo from requireAgent() into getAgent() so the session file
is only read once per command invocation.
@disnet

disnet commented Feb 28, 2026

Copy link
Copy Markdown
Owner

ah fantastic! this has been bugging me for a while. thanks for tracking it down

@disnet

disnet commented Feb 28, 2026

Copy link
Copy Markdown
Owner

oh could you run formatting to let CI pass?

@tijs

tijs commented Feb 28, 2026

Copy link
Copy Markdown
Contributor Author

Yeah will do! Weird I thought all tests passed but perhaps I forgot the formatter

@tijs

tijs commented Feb 28, 2026

Copy link
Copy Markdown
Contributor Author

I think it should be ok now?

@disnet
disnet merged commit 9db3c9d into disnet:main Feb 28, 2026
1 check passed
@disnet

disnet commented Feb 28, 2026

Copy link
Copy Markdown
Owner

perfect, thanks!

@disnet disnet mentioned this pull request Feb 28, 2026
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.

CLI: session expires after ~1 hour due to OAuth client_id mismatch on token refresh

2 participants