Summary
Refactor the third-party account linkage callback endpoint (/api/connect/github/callback) to verify user identity via a Redis state nonce instead of a direct HTTP header authentication check. This allows browser-level GET redirects from GitHub to authenticate without throwing a 401.
Contexts
In apps/backend/src/routes/connect.ts, the GET endpoint /github/callback is decorated with preHandler: [app.authenticate].
Because OAuth redirects are browser-initiated GET page loads, the user's browser redirects from github.com straight to /api/connect/github/callback?code=...&state=.... The client cannot programmatically inject an Authorization: Bearer <token> header into this browser-level redirect. Since fastify-jwt is registered in app.ts without any cookie extraction support, the request.jwtVerify() call in app.authenticate fails to find a token and immediately terminates the callback flow with a 401 Unauthorized error.
Tasks
Acceptance Criteria
Area
backend
Difficulty
Hard
Summary
Refactor the third-party account linkage callback endpoint (
/api/connect/github/callback) to verify user identity via a Redis state nonce instead of a direct HTTP header authentication check. This allows browser-level GET redirects from GitHub to authenticate without throwing a 401.Contexts
In
apps/backend/src/routes/connect.ts, the GET endpoint/github/callbackis decorated withpreHandler: [app.authenticate].Because OAuth redirects are browser-initiated GET page loads, the user's browser redirects from
github.comstraight to/api/connect/github/callback?code=...&state=.... The client cannot programmatically inject anAuthorization: Bearer <token>header into this browser-level redirect. Sincefastify-jwtis registered inapp.tswithout any cookie extraction support, therequest.jwtVerify()call inapp.authenticatefails to find a token and immediately terminates the callback flow with a401 Unauthorizederror.Tasks
preHandler: [app.authenticate]from/github/callbackinapps/backend/src/routes/connect.ts.stateparameter redirect value.noncereceived in the callback against the Redis store to retrieve the matchinguserId.userIdto create or update the correspondingoAuthTokenin PostgreSQL.Acceptance Criteria
401 Unauthorizederrors.oAuthTokenis correctly updated or created under the correct authenticated user.Area
backendDifficulty
Hard