Connected-clients UI (list authorized OAuth clients + revoke)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- postgresql, react, typescript
- Domain
- authentication, backend, frontend
Research direction
Start with server/src/services/OAuthService.ts, the OAuth routes in server/src/api/oauth.ts or server/src/api/user.ts, and the ownership checks in middleware/resource.ts. Read the existing OAuth service and user route patterns, then inspect server/test/oauth.test.ts. Done means users can list their authorized clients and revoke a client’s access and refresh tokens, with owner checks covered by tests and a Connected apps entry in ui/src/components/navbar.tsx.
Written by the indexing model from the issue text.
Description
Optional: a navbar affordance listing the OAuth clients the user has authorized, with a revoke button (delete their oauth_token rows). Nice-to-have now that connecting is one click.
Effort: S
Migrated from ENHANCEMENTS.md (§6 AI / MCP integration).
Implementation notes
Priority: medium — Real security/self-service value (users currently cannot revoke MCP OAuth grants themselves) but low usage volume and no core-path or stability impact.
Purpose
Gives users visibility into which third-party OAuth clients (Claude Desktop, claude.ai connectors, etc.) currently hold live access to their RobocodeJs account via MCP, and a self-service way to cut that access off — closing a real gap since oauth_token rows today can only be removed by the SDK's own /revoke endpoint (which requires the client to call it, not the user).
Implementation approach
- Server:
server/src/services/OAuthService.ts— addlistTokensForUser(userId)(e.g.SELECT DISTINCT clientId, kind, MAX(createdTimestamp), MAX(expiresAt) FROM oauth_token WHERE userId=$1 GROUP BY clientId, kind, then join client names viagetClient/oauth_client) anddeleteTokensForUserAndClient(userId, clientId)(bulkDELETE FROM oauth_token WHERE userId=$1 AND clientId=$2, covering both access+refresh rows) alongside the existinggetToken/deleteToken/sweepExpired. - Server: new routes in
server/src/api/oauth.ts(or a newoauthClients.tsmounted likeuser.ts) —GET /api/user/:userId/oauth-clientsandDELETE /api/user/:userId/oauth-clients/:clientId, gated byauth(true)+loadUser+requireOwner(middleware/resource.ts), following theuser.ts/app.tspattern exactly. - UI:
ui/src/components/navbar.tsx— add a "Connected apps" item under the existing userNavDropdown(next to "Sign out"), opening a small modal/page (mirrorarenaRoster.tsx's show/onHide modal pattern) listing client name, scope, granted/expiry, with a revoke button calling the new DELETE endpoint. - No bot-facing
compiler.tssurface, no simulation/SSE involvement — this is pure account-management REST + UI, isolated from the sandbox and tick loop.
Key details to plan
- No DB migrations exist yet (#142) — new queries must use the current
oauth_token/oauth_clienttables as-is; no schema change needed sinceuserId/clientIdalready exist per-row. - Revoking must delete both
kind='access'andkind='refresh'rows for that user+client so a lingering refresh token can't mint a new access token post-revoke. - Security: this is a new authenticated, owner-scoped surface — must reuse
requireOwner, not justauth(true), or one user could enumerate/revoke another's grants (same IDOR class already fixed elsewhere per the OWASP audit). - Testing: extend
server/test/oauth.test.ts(pg-mem-backed, already mocksauthand exercisesoauthServicedirectly) with list/revoke-by-user-and-client cases; add a thin UI test ifnavbar/arenaRosterhave existing RTL coverage. - Depends conceptually on #142 (migrations) only as future cleanup, not a blocker. Effort matches the issue's S label — no simulation/determinism/sandbox risk, small additive CRUD + one navbar entry; main risk is getting the ownership check right.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- Avg merge
- 8m
- Merged PRs (30d)
- 8
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from LeeAdcock/robocodeJs.com
-
priority: medium tech-debt
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
LeeAdcock/robocodeJs.com#411 ·
Maintainers usually reply within 1 day
-
enhancement priority: medium
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
LeeAdcock/robocodeJs.com#254 ·
Maintainers usually reply within 1 day
-
good first issue priority: low tech-debt
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
LeeAdcock/robocodeJs.com#146 ·
Maintainers usually reply within 1 day
-
dependencies priority: low tech-debt
Difficulty 1/5 Under an hour Newbie friendliness 15/100
LeeAdcock/robocodeJs.com#413 ·
Maintainers usually reply within 1 day
-
priority: low tech-debt
Difficulty 3/5 Half a day Newbie friendliness 32/100
LeeAdcock/robocodeJs.com#412 ·
Maintainers usually reply within 1 day
All issues in LeeAdcock/robocodeJs.com
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
homarr-labs/homarr#7191 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
AvaProtocol/ava-sdk-js#276 ·
Maintainers usually reply within 1 day
-
useFragment does not require `variables` when the fragment's variables type has required fieldsOpen
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
apollographql/apollo-client#13493 ·
Maintainers usually reply within 1 day