Repository navigation
Make Git tokens reusable for API and MCP with configurable expiration - #8
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b897abb08c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (c.req.path.startsWith('/api/') && /^Bearer (?:wiki|git)_/i.test(authorization)) { | ||
| const user = await authenticatePersonalToken(c.env, authorization.slice(7).trim()); | ||
| if (!user) return c.json({ error: 'Invalid or expired API token' }, 401, { 'Cache-Control': 'no-store' }); | ||
| c.set('user', user); c.set('apiTokenAuthenticated', true); | ||
| return next(); |
There was a problem hiding this comment.
Prevent API tokens from minting browser sessions via QR login
Because this authenticates personal tokens for every /api/* route, a token holder can call /api/qr-login/start, approve that request through /api/qr-login/approve using the bearer token, and redeem the secret for a six-hour browser session cookie. That cookie then passes requireBrowserSession, allowing the holder to rotate/revoke personal tokens or MCP keys despite the intended browser-session-only boundary, and a stolen token can therefore be converted into persistent account access. Exclude the QR approval flow from bearer authentication or explicitly require a browser session there.
Useful? React with 👍 / 👎.
| const authorization = c.req.header('Authorization') || ''; | ||
| if (c.req.path.startsWith('/api/') && /^Bearer (?:wiki|git)_/i.test(authorization)) { | ||
| const user = await authenticatePersonalToken(c.env, authorization.slice(7).trim()); | ||
| if (!user) return c.json({ error: 'Invalid or expired API token' }, 401, { 'Cache-Control': 'no-store' }); |
There was a problem hiding this comment.
Let MCP return its bearer authentication challenge
When an expired, revoked, or malformed wiki_/git_ token is sent to /api/mcp, this early response prevents resolveBearerAuth from handling it. The MCP-specific handler deliberately returns a WWW-Authenticate header containing the protected-resource metadata so clients can initiate reauthentication, whereas this response has no challenge header; clients using a personal token will therefore stop with a generic 401 when it expires instead of entering the MCP authentication flow. Skip personal-token session handling for /api/mcp and let its existing bearer resolver validate these tokens.
Useful? React with 👍 / 👎.
Git credentials were limited to Git with a fixed 30-day lifetime. Personal API tokens now work as Git passwords and Bearer credentials for Wiki APIs and MCP. Users can select 7/30/90/365 days, a custom expiration, or no expiration from Git editing or the new /tokens page linked in personal settings.
Existing git_ tokens and /api/me/git-token remain compatible; new tokens use wiki_ and /api/me/api-token. Storage remains hashed and rotation replaces the previous token. Every request checks the current account, permissions, ban status and expiration. Only authenticated Bearer requests bypass browser CSRF and interactive Turnstile checks; token management requires a browser session. Account deletion revokes personal credentials. Git non-fast-forward rejection remains intact.
Validation: server/client typechecks, real Git transport tests, eight service tests covering Worker API and MCP authentication, API writes, expiration, rotation, revocation, bans, compatibility, cookie CSRF and management isolation; full build and all 42 localized shells pass. Policy templates and documentation updated.