T5: FIT OAuth client + docs/fit-auth.md #5
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "t5-fit-oauth"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
T5: FIT OAuth client
Stacked on #4 (
t4-crypto-token-store) → #3 → #2 → #1. Merge those first.What
src/lib/fit-auth.ts:buildAuthorizeUrl(SPEC scopes,state, S256code_challenge) andexchangeCode.refreshTokens/fitRefresher, which plugs into the T4 token store and mapsinvalid_granttoRefreshRejectedError.checkToken(POSTs the token so it stays out of URLs).createPkce/randomToken/timingSafeEqual, andfitAuthConfigFromEnv(single callbackPUBLIC_URL/auth/callback).cvut:grades:course-restrictedis never requested. Scopes are tokenized before the denylist check, so whitespace smuggling is blocked.error_descriptionechoes the submitted token or code ("Invalid refresh token: <token>").FitAuthErrorkeeps only the OAuth error code and HTTP status. Tests assert that secrets never appear in errors.docs/fit-auth.md: endpoints, observed responses, error mapping, PKCE notes, and open questions for the first real login.zod(also needed by T8).Probed the live server (no user login, credentials never printed)
/oauth/authorize,/oauth/token, public/oauth/check_token,/oauth/userinfo.client_credentialsreturns "Unauthorized grant type", meaning the client authenticated. A wrong secret returns401 Bad credentials.client_secret_postis rejected with 401.checkToken(bogus)→null, bogus refresh →RefreshRejectedError, wrong secret →FitAuthError unauthorized (401), and authorize → 302 to the login page.Verified
bun run lint && bun run typecheck && bun run test: 79 tests, 24 of them for this client. They include the RFC 7636 Appendix B PKCE vector, RFC 6749 Basic encoding, request shapes, error mapping and no-leak assertions./auth/callbackroute comes in T6.Astra review (gpt-6-astra)
Fixed (all four):
cvut:grades:course-restricted→ scopes are tokenized before the denylist check.encodeURIComponentleft!'()~unencoded in Basic credentials →URLSearchParamsform encoding.token_typewas accepted →beareris required (RFC 6749 §7.1).{}fromcheck_tokenlooked like a valid introspection →client_idis required.Fixes 3 and 4 make the client stricter than strictly needed for the probed error paths. They're listed in
docs/fit-auth.mdto confirm on the first real login.Needs you (soon)
T6 (Better Auth login) comes next. Once it lands I'll ask for one browser login at
http://localhost:3000. That answers the open questions indocs/fit-auth.md: refresh tokens, lifetimes, rotation and PKCE.🤖 Generated with Claude Code