Skip to content

fix(auth0-express): stop leaking internal error detail from handlers - #26

Open
frederikprijck wants to merge 9 commits into
mainfrom
fix/sdk-4-sanitize-handler-errors
Open

fix(auth0-express): stop leaking internal error detail from handlers#26
frederikprijck wants to merge 9 commits into
mainfrom
fix/sdk-4-sanitize-handler-errors

Conversation

@frederikprijck

@frederikprijck frederikprijck commented Jul 9, 2026

Copy link
Copy Markdown
Member

Summary

The auth handlers echoed error.name/error.message (and error.cause.error_description) verbatim in HTTP responses, leaking internal/library error detail useful for probing the auth flow.

Changes

The three browser-facing handlers (login, callback, logout) now route failures through Express's next(error) instead of writing error detail to the response. Express's error middleware owns the response; the SDK no longer authors the leak. Their signatures gained a next param, threaded through the router.

The back-channel logout handler is called server-to-server by the OP and must return a spec-shaped response (OIDC Back-Channel Logout 1.0 §2.8: 200/204 on success, 400 on failure), so it keeps owning its own response rather than delegating to next(). The SDK-4 change there is dropping the leaked error.message from the bare 400 body.

Note: this changes the public error-response contract for the browser-facing handlers. Apps that want OAuth error codes should mount their own error handler. See the new Error Handling section in the README — internal detail is only fully suppressed when NODE_ENV=production and/or a custom error handler is mounted, per Express's default behavior.

Tests

Handler + index specs updated to the sanitized contract. The error-leak tests run under NODE_ENV=production (matching Express's real sanitization behavior) and were verified via a leak-revert to genuinely fail if a handler leaks. auth0-express suite: 185/185 pass.

frederikprijck and others added 5 commits July 9, 2026 20:20
Route handler failures through next(error) instead of echoing
error.name/message/error_description to the client, so Express error
middleware owns the response and internal detail is not disclosed.

SECURITY: SDK-4 — verbose error messages (CWE-209).
…ailure

The SDK-4 sanitization routed backchannel-logout failures through next(error),
which Express turns into a 500. OIDC Back-Channel Logout §2.8 requires the RP to
respond with 400 Bad Request when the logout request is invalid or the logout
fails. Return 400 with an empty body on any failure — spec-compliant status,
no internal error detail leaked to the caller.
…ia next()

Instead of writing the 400 directly (which bypasses Express error middleware
and loses server-side observability), forward a new Error carrying status: 400
through next(). Express's default handler emits the spec-mandated 400 (OIDC
Back-Channel Logout §2.8) from err.status, the app's error middleware can log
it, and the original error is preserved on cause without leaking to the client.
@frederikprijck
frederikprijck marked this pull request as draft August 25, 2026 10:04
…estError

Introduce GenericRequestError<TError>, an HTTP-status-bearing error for
forwarding to Express via next(). Express's default handler reads err.status,
so it yields the OIDC-mandated 400 (Back-Channel Logout §2.8) with no custom
handler, and omits err.message from the client response in production. The
original failure is preserved on cause for app error middleware to log or
branch on. Avoids a name clash with auth0-server-js's BackchannelLogoutError
and keeps the wrapper reusable for other handlers.
…f next()

The back-channel logout endpoint is called server-to-server by the OP, so it
should not flow through the app's Express error middleware (which is meant for
its browser-facing auth routes and would otherwise return a config-dependent
HTML page to Auth0). The handler now owns its response: bare 400 on failure per
OIDC Back-Channel Logout §2.8, 204 on success, with no internal detail leaked.

This drops GenericRequestError (introduced earlier in this branch and unused
now), so the app's global error handler only ever receives the real SDK error
instance, top-level, from the browser-facing handlers. README updated to
document the split and how to log backchannel failures via a custom route.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants