fix(api): support Fetch Request in getAuthProviderHeader#1750
Conversation
`getAuthProviderHeader` previously called `Object.keys(event.headers)` to locate the auth-provider header. This works for Lambda `APIGatewayProxyEvent` (where `headers` is a plain object) but silently returns `[]` for a Fetch `Request`, whose `headers` is a `Headers` class instance. As a result, requests using Bearer-token auth on the new Web Standard handler path were treated as unauthenticated even with a valid `auth-provider` and `Authorization` header. When `headers` exposes a `.get()` method, look the value up via the `Headers` API directly before falling back to plain-object iteration. Adds a regression test covering the Fetch Request + Bearer token case.
✅ Deploy Preview for cedarjs canceled.
|
Greptile SummaryThis PR fixes a silent auth failure on the Web Standard / middleware path by correcting
Confidence Score: 5/5Safe to merge — a narrowly scoped additive fix with a direct regression test and no changes to the Lambda path's observable behaviour. The change is a two-branch dispatch that only adds a new code path for Fetch requests while leaving the Lambda path intact. The root cause is well understood, the fix is minimal, and the new test exercises the exact failure scenario end-to-end. No existing tests were modified, and the docs in No files require special attention. Important Files Changed
Reviews (3): Last reviewed commit: "minor tweaks" | Re-trigger Greptile |
|
Support for webstandard fetch handlers is a work in progress. Did you see Greptile's review comment? Are they helpful? |
Addresses review feedback on cedarjs#1750 flagging that the original fix duck-typed `headers.get` to detect a Fetch `Request`, duplicating the role of the existing `isFetchApiRequest` helper in `packages/api/src/transforms.ts`. That helper is the canonical dispatch used elsewhere in the package (including `getEventHeader` in `packages/api/src/event.ts`), so introducing a second detection path can drift over time — e.g. if the ponyfill's constructor name changes or a new Fetch-like request type appears. Refactor `getAuthProviderHeader` to dispatch on `isFetchApiRequest`: - Fetch `Request`: read `event.headers.get(AUTH_PROVIDER_HEADER)` directly. `Headers.get` is already case-insensitive, so no manual normalisation is needed. - Lambda `APIGatewayProxyEvent`: keep the existing `Object.keys(headers).find(...)` walk. API Gateway preserves the client's header case in `event.headers`, so the case-insensitive match has to stay defensive for proper-case (`Auth-Provider`) and upper-case (`AUTH-PROVIDER`) clients. Pure refactor — no behavioural change on either path. Regression test in `getAuthenticationContext.test.ts` continues to cover the Fetch Request + Bearer-token path. `yarn test` in `packages/api` — 245 passing. `yarn build` — clean (ESM + CJS).
|
@Tobbe Yeah, fair — greptile had a point. Refactored to dispatch on |
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx run-many -t build:pack --exclude create-ceda... |
✅ Succeeded | 5s | View ↗ |
nx run-many -t build |
✅ Succeeded | 3m 58s | View ↗ |
☁️ Nx Cloud last updated this comment at 2026-05-11 21:44:13 UTC
|
The changes in this PR are now available on npm. Try them out by running Or try it in a new app with |

Problem
Bearer-token auth silently fails when an
@cedarjs/apihandler is invoked via the Web Standard / middleware path (a FetchRequestrather than a LambdaAPIGatewayProxyEvent). A request with validauth-providerandAuthorization: Bearer …headers comes back as unauthenticated, andgetAuthenticationContextreturnsundefined— so any auth provider that uses Bearer tokens (Auth0, Supabase non-cookie, Clerk JWT, custom JWT, etc.) is broken on that path.Root cause
getAuthProviderHeader(inpackages/api/src/auth/index.ts) does:For a Lambda event,
event.headersis a plain object, soObject.keysreturns the header names. For a FetchRequest,event.headersis aHeadersinstance —Object.keys(headersInstance)returns[], the function returnsundefined, and the short-circuit at the top ofgetAuthenticationContextdecides the request is unauthenticated:So the Bearer-token code path is never even attempted on the middleware path.
Fix
When
headersexposes a.get()method (theHeadersAPI), look the value up directly viaheaders.get('auth-provider'). Fall back to the existing plain-object iteration for Lambda callers, so existing handlers behave exactly as they do today.Surface area is intentionally tiny — one function, one file — and the Lambda path is the explicit fallback, so the change is additive rather than a behaviour swap.
Checks
Per
CONTRIBUTING.md:yarn check— clean (no constraint or dedupe issues)yarn testinpackages/api— 245 passing, including a new regression test inpackages/api/src/auth/__tests__/getAuthenticationContext.test.tsthat exercisesRequest+auth-providerheader +Authorization: Bearer …yarn buildinpackages/api— clean (ESM + CJS)yarn lint— clean (via pre-commit hook)No new dependencies.