Skip to content

Support comma-separated Cookie strings for browser cloudflare compatibility #54

@j-xzy

Description

@j-xzy

Background

While using betterauth with the bear plugin in a Cloudflare Workers environment, I encountered a persistent 401 Unauthorized error. The issue was traced back to the following code pattern used to add the session token to the request headers:

// packages/better-auth/src/plugins/bearer/index.ts
const headers = new Headers({
  ...Object.fromEntries(existingHeaders?.entries()),
});
headers.append(
  "cookie",
  `${c.context.authCookies.sessionToken.name}=${signedToken}`,
);

The root cause is a runtime discrepancy in the Headers object. When appending an auth cookie to existing headers, Cloudflare/browsers use a comma separator ('cookie1=a, cookie2=b'), while the existing parser only supports semicolons. This causes the auth cookie to be parsed incorrectly, leading to authentication failure.

The Solution

function parseCookies(str: string): Map<string, string> {
	if (typeof str !== "string") {
		throw new TypeError("argument str must be a string");
	}

	const cookies: Map<string, string> = new Map();
	if (!str) {
		return cookies;
	}

	const pairs = str.split(/[;,]\s*/);

	for (const pair of pairs) {
		const eqIdx = pair.indexOf("=");

		if (eqIdx === -1) {
			continue;
		}

		const key = pair.slice(0, eqIdx).trim();

		if (!cookies.has(key)) {
			let val = pair.slice(eqIdx + 1).trim();

			if (val.codePointAt(0) === 0x22) { // 0x22 is the code for "
				val = val.slice(1, -1);
			}

			cookies.set(key, tryDecode(val));
		}
	}

	return cookies;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions