Skip to content

Commit

Permalink
Merge pull request #301 from auth0/cookie-chunk-length
Browse files Browse the repository at this point in the history
Chunked cookies should not exceed browser max
  • Loading branch information
adamjmcgrath authored Feb 18, 2021
2 parents c553863 + d5b0d66 commit 8fa0230
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
26 changes: 21 additions & 5 deletions src/auth0-session/cookie-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { encryption as deriveKey } from './utils/hkdf';
import createDebug from './utils/debug';
import { getAll as getCookies, clear as clearCookie, set as setCookie } from './utils/cookies';
import { Config } from './config';
import { CookieSerializeOptions } from 'cookie';
import { CookieSerializeOptions, serialize } from 'cookie';

const debug = createDebug('cookie-store');
const epoch = (): number => (Date.now() / 1000) | 0; // eslint-disable-line no-bitwise
const CHUNK_BYTE_SIZE = 4000;
const MAX_COOKIE_SIZE = 4096;
const alg = 'dir';
const enc = 'A256GCM';

Expand All @@ -20,6 +20,8 @@ export default class CookieStore {

private currentKey: JWK.OctKey | undefined;

private chunkSize: number;

constructor(public config: Config) {
const secrets = Array.isArray(config.secret) ? config.secret : [config.secret];
this.keystore = new JWKS.KeyStore();
Expand All @@ -31,6 +33,20 @@ export default class CookieStore {
}
this.keystore.add(key);
});

const {
cookie: { transient, ...cookieConfig },
name: sessionName
} = this.config.session;
const cookieOptions: CookieSerializeOptions = {
...cookieConfig
};
if (!transient) {
cookieOptions.expires = new Date();
}

const emptyCookie = serialize(`${sessionName}.0`, '', cookieOptions);
this.chunkSize = MAX_COOKIE_SIZE - emptyCookie.length;
}

private encrypt(payload: string, headers: { [key: string]: any }): string {
Expand Down Expand Up @@ -172,11 +188,11 @@ export default class CookieStore {
debug('found session, creating signed session cookie(s) with name %o(.i)', sessionName);
const value = this.encrypt(JSON.stringify(session), { iat, uat, exp });

const chunkCount = Math.ceil(value.length / CHUNK_BYTE_SIZE);
const chunkCount = Math.ceil(value.length / this.chunkSize);
if (chunkCount > 1) {
debug('cookie size greater than %d, chunking', CHUNK_BYTE_SIZE);
debug('cookie size greater than %d, chunking', this.chunkSize);
for (let i = 0; i < chunkCount; i++) {
const chunkValue = value.slice(i * CHUNK_BYTE_SIZE, (i + 1) * CHUNK_BYTE_SIZE);
const chunkValue = value.slice(i * this.chunkSize, (i + 1) * this.chunkSize);
const chunkCookieName = `${sessionName}.${i}`;
setCookie(res, chunkCookieName, chunkValue, cookieOptions);
}
Expand Down
19 changes: 19 additions & 0 deletions tests/auth0-session/cookie-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@ describe('CookieStore', () => {
expect(session.claims).toHaveProperty('big_claim');
});

it('should limit total cookie size to 4096 Bytes', async () => {
const path =
'/some-really-really-really-really-really-really-really-really-really-really-really-really-really-long-path';
const baseURL = await setup({ ...defaultConfig, session: { cookie: { path } } });
const appSession = encrypted({
big_claim: randomBytes(5000).toString('base64')
});
expect(appSession.length).toBeGreaterThan(4096);
const cookieJar = toCookieJar({ appSession }, baseURL);
await get(baseURL, '/session', { cookieJar });
const cookies: { [key: string]: string } = cookieJar
.getCookiesSync(`${baseURL}${path}`)
.reduce((obj, value) => Object.assign(obj, { [value.key]: value + '' }), {});
expect(cookies['appSession.0']).toHaveLength(4096);
expect(cookies['appSession.1']).toHaveLength(4096);
expect(cookies['appSession.2']).toHaveLength(4096);
expect(cookies['appSession.3']).toHaveLength(1568);
});

it('should handle unordered chunked cookies', async () => {
const baseURL = await setup(defaultConfig);
const appSession = encrypted({ sub: '__chunked_sub__' });
Expand Down

0 comments on commit 8fa0230

Please sign in to comment.