Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions