From 4d9ac2b5ddf3be6b6763dc02e865b9dcca6adc0b Mon Sep 17 00:00:00 2001 From: Ivan Pereira <183991+ivanrvpereira@users.noreply.github.com> Date: Tue, 14 Jul 2026 12:54:10 +0100 Subject: [PATCH] fix(auth): accept bare session tokens from cookie env vars parseBrowserAuthInput returns an access-only credential for a bare __Secure-next-auth.session-token value, which /perplexity-login --browser accepts but credentialsFromEnvironment rejected because it required .cookies. Only reject when parsing fails entirely. --- src/auth/login.ts | 2 +- test/auth/login.test.ts | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/auth/login.ts b/src/auth/login.ts index da76165..a1fa41d 100644 --- a/src/auth/login.ts +++ b/src/auth/login.ts @@ -58,7 +58,7 @@ function credentialsFromEnvironment(): StoredToken | null { const value = normalizeInput(process.env[key]); if (value) { const credentials = parseBrowserAuthInput(value); - if (!credentials?.cookies) { + if (!credentials) { throw new AuthError( "NO_TOKEN", `${key} is set but does not contain a signed-in Perplexity browser cookie. ${browserAuthFailureMessage(value)}`, diff --git a/test/auth/login.test.ts b/test/auth/login.test.ts index f0a90bd..c19f250 100644 --- a/test/auth/login.test.ts +++ b/test/auth/login.test.ts @@ -314,6 +314,30 @@ describe("auth/login", () => { expect(saveTokenMock).toHaveBeenCalledTimes(1); }); + test("authenticate accepts a bare session token from PI_PERPLEXITY_COOKIE", async () => { + process.env.PI_AUTH_NO_BORROW = "1"; + const browserToken = createJwt(Date.now() + 2 * 60 * 60 * 1000); + process.env.PI_PERPLEXITY_COOKIE = browserToken; + + const loadTokenMock = mock(async () => null); + const saveTokenMock = mock(async (_token: StoredToken) => undefined); + const clearTokenMock = mock(async () => undefined); + + mock.module("../../src/auth/storage.js", () => ({ + loadToken: loadTokenMock, + saveToken: saveTokenMock, + clearToken: clearTokenMock, + })); + + const { authenticate } = await importLoginModule(); + + const token = await authenticate(); + + expect(token.access).toBe(browserToken); + expect(token.cookies).toBe(undefined); + expect(saveTokenMock).toHaveBeenCalledTimes(1); + }); + test("authenticate rejects PI_PERPLEXITY_COOKIE without a signed-in session cookie", async () => { process.env.PI_AUTH_NO_BORROW = "1"; process.env.PI_PERPLEXITY_COOKIE = "pplx.visitor-id=visitor; cf_clearance=clearance";