Skip to content

Commit ef507a6

Browse files
fix: use Sec-Fetch-Site header for cookie authentication validation (#15751)
## Summary - Adds `Sec-Fetch-Site` header validation for cookie-based authentication when `Origin` header is absent - Accepts cookies for `same-origin` and `same-site` requests - Rejects cookies for `cross-site` and `none` requests - Falls back to rejecting cookies when `Sec-Fetch-Site` is absent and `csrf` is configured (non-browser clients should use `Authorization` header) --------- Co-authored-by: Jessica Chowdhury <jessica@trbl.design>
1 parent 46e43fc commit ef507a6

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

packages/payload/src/auth/extractJWT.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ const extractionMethods: Record<string, ExtractionMethod> = {
99
Bearer: ({ headers }) => {
1010
const jwtFromHeader = headers.get('Authorization')
1111

12-
// allow RFC6750 OAuth 2.0 compliant Bearer tokens
13-
// in addition to the payload default JWT format
12+
// RFC6750 OAuth 2.0 Bearer token
1413
if (jwtFromHeader?.startsWith('Bearer ')) {
1514
return jwtFromHeader.replace('Bearer ', '')
1615
}
1716

1817
return null
1918
},
2019
cookie: ({ headers, payload }) => {
21-
const origin = headers.get('Origin')
2220
const cookies = parseCookies(headers)
2321
const tokenCookieName = `${payload.config.cookiePrefix}-token`
2422
const cookieToken = cookies.get(tokenCookieName)
@@ -27,10 +25,30 @@ const extractionMethods: Record<string, ExtractionMethod> = {
2725
return null
2826
}
2927

30-
if (!origin || payload.config.csrf.length === 0 || payload.config.csrf.indexOf(origin) > -1) {
28+
const origin = headers.get('Origin')
29+
30+
// Origin present — validate against csrf allowlist
31+
if (origin) {
32+
if (payload.config.csrf.length === 0 || payload.config.csrf.includes(origin)) {
33+
return cookieToken
34+
}
35+
return null
36+
}
37+
38+
// No Origin and no csrf configured — no allowlist to enforce
39+
if (payload.config.csrf.length === 0) {
40+
return cookieToken
41+
}
42+
43+
// No Origin with csrf configured — fall back to Sec-Fetch-Site
44+
const secFetchSite = headers.get('Sec-Fetch-Site')
45+
46+
// Allow same-origin, same-site, and direct navigations (none)
47+
if (secFetchSite === 'same-origin' || secFetchSite === 'same-site' || secFetchSite === 'none') {
3148
return cookieToken
3249
}
3350

51+
// Reject cross-site requests and missing header (non-browser clients)
3452
return null
3553
},
3654
JWT: ({ headers }) => {

0 commit comments

Comments
 (0)