feat(callback): centralize logging and add errorRedirectUrl option#74
feat(callback): centralize logging and add errorRedirectUrl option#74
Conversation
Centralizes the per-error-path `console.error` calls in `errorResponse` so every callback failure (missing code, getAuthkit throws, handleCallback throws, onSuccess throws) emits exactly one `[authkit-tanstack-react-start] OAuth callback failed:` line. Removes the two scattered logs at the prior call sites. Adds a new opt-in `errorRedirectUrl` option to `HandleCallbackOptions`. When set (and `onError` is not), `errorResponse` returns a 302 to the resolved URL with the verifier-delete cookies attached. Accepts absolute URLs and relative paths (resolved against the request origin). Malformed values fall back to the existing path-dependent JSON response with a separate config-warning log. `onError` still wins precedence when both are set, and errors thrown inside `onError` are explicitly NOT caught (locked in by a regression test). Updates types JSDoc, README (Sentry + sign-in error page examples + open- redirect note), and adds 12 new test cases covering all error paths.
Greptile SummaryThis PR centralises error logging in Confidence Score: 5/5Safe to merge — no new P0/P1 issues found; both previously raised concerns are addressed in the current revision. All error paths are covered by tests (32/32), the two prior review findings (swallowed setupError and the dynamic status in the fallback log) are fixed in the current code, the open-redirect risk is explicitly documented and scoped to developer-controlled config, and backward compatibility is preserved. No files require special attention. Important Files Changed
|
Preserve the original getAuthkit() error instead of replacing it with a synthetic 'AuthKit not initialized' message so the central log emits the real failure reason. Interpolate defaultStatus into the malformed errorRedirectUrl log message so it correctly says 'JSON 400' on the missing-code path instead of always saying 'JSON 500'. Co-Authored-By: nick.nisi@workos.com <nick@nisi.org>
Summary
handleCallbackRoutenow emits exactly one[authkit-tanstack-react-start] OAuth callback failed:line via a single log point at the top oferrorResponse. Removes the two scatteredconsole.errorcalls at the previous setup-failure and handle-callback-failure sites. The missing-codeandonSuccess-throws paths now also log uniformly.buildVerifierDeleteHeaders's own auxiliary log is left untouched (different concern).errorRedirectUrl. New string option onHandleCallbackOptions. When set (andonErroris not),errorResponsereturns a 302 withLocationset to the resolved URL plus the verifier-delete cookies. Accepts absolute URLs and relative paths (resolved againstrequest.url). Malformed values fall back to the existing path-dependent JSON response (400 or 500) with a separate config-warning log line.onErrorstill wins precedence when both are set. Errors thrown insideonErrorare explicitly NOT caught by the SDK — locked in by a regression test against the newerrorRedirectUrltry/catch broadening. JSON-fallback shape, status codes, and delete-cookie headers unchanged when neither option is set.The customer incident this addresses: a stale verifier cookie or PKCE state mismatch caused the SDK to surface raw JSON to the user's browser. Callers who set
errorRedirectUrlnow bounce users to a route they own (e.g.,/sign-in?error=auth_failed) with verifier-delete cookies still attached. Callers who want observability can wire Sentry insideonError(or rely on the centralconsole.erroringestion) and get a uniform signal.What's in the diff
src/server/types.tserrorRedirectUrl?: stringfield with JSDoc covering relative/absolute resolution, precedence vsonError, malformed-value fallback, and open-redirect warning. Adds throw-not-caught note toonErrorJSDoc.src/server/server.tsconsole.errorat the prior setup-failure and handle-callback-failure call sites. Adds centralconsole.errorat the top oferrorResponse. AddserrorRedirectUrlbranch between theonErrorshort-circuit and JSON fallback, with a tightly scoped try/catch aroundnew URL()that logs a config warning and falls through to JSON on malformed input.src/server/server.spec.tsconsole.errorspy to top-levelbeforeEach/afterEach. Adds 12 new test cases (4 fromit.eachfor log-fires-once across all error paths, plus explicit cases for absolute/relativeerrorRedirectUrl, precedence, malformed-URL fallback on both 400 and 500 paths,onSuccess-throws routing,returnPathname-ignored-on-error, and a regression test thatonErrorthrows are not caught).README.mdhandleCallbackRoutesection with three examples (basic, sign-in error page, Sentry capture), updates the Options list with the new field, and adds the precedence + open-redirect notes.Backward compatibility
Non-breaking. With neither
onErrornorerrorRedirectUrlset, the response is semantically identical to today:400for missingcode,500for setup/handleCallback/onSuccess failures,Content-Type: application/json, same JSON body shape, same delete-cookie headers. Existing tests (and the example app's existingonError-using callback) continue to pass.Test plan
pnpm test src/server/server.spec.ts— 32/32 (was 20/20 before).pnpm test— full suite, 215/215.pnpm build— typecheck + library build.cd example && pnpm build— no Node-only externalization warnings in the client chunk.codeshows JSON 400, exactly oneOAuth callback failed:log line.errorRedirectUrlonly: 302 Location + verifier cookies cleared.onError+errorRedirectUrl:onErrorwins, both logs fire (central + user's), no redirect.errorRedirectUrl(http://[::1): falls back to JSON, both logs fire in order (central first, malformed second).errorRedirectUrl: '/sign-in?error=auth_failed'): browser lands on/sign-in?error=auth_failedinstead of raw JSON.Out of scope
Per the contract:
authkit-nextjs.onError.errorRedirectUrl— developer-controlled value; documented as such.authkit-nextjsto match — separate repo, separate release.