Handling Cookies with Size Over 4096 Bytes - Best Practices

638 Views Asked by At

I'm facing a challenge with handling cookies in a web application where I store both an access token and a refresh token issued by Microsoftonline. The combined size of these tokens can sometimes exceed the 4096-byte limit imposed by most browsers. I want to ensure that I follow best practices for managing this situation.

My question is: What is the recommended approach to handle cookies when their size exceeds 4096 bytes? Should I split the cookies into two separate ones, one for the access token and the other for the refresh token? Alternatively, is it better to store the access token on the server side and only include an identifier in the cookie?

I appreciate the convenience of having all necessary information stored in the cookie for stateless operation, but I'm concerned about exceeding the browser's cookie size limit. What are the pros and cons of these two approaches, and are there any other best practices for managing cookies in situations like this?

2

There are 2 best solutions below

1
Gary Archer On BEST ANSWER

Here are some suggestions. Note that desktop and mobile browser limits for the cookie request header are 4KB. Some HTTP servers, such as NGINX, also have a 4KB default limit for header sizes. Each host can issue up to 20 cookies according to RFC 2109.

COOKIE PATHS

You will probably have 4 cookies in total. For any particular request, use of paths should then ensure that you stay under the 4KB limit. Here is an example:

  • AT: the access token cookie. with a path of /
  • CSRF: an anti forgery token for data changing commands, also with a path of /
  • RT: the refresh token cookie, with a path of /refresh
  • ID: the ID token cookie, with a path of /claims

When cookies are stored in tokens, use a strong symmetric security algorithm to encrypt them. The key must be private to the backend, and rotated occasionally.

EFFICIENT TOKENS

Where supported, issue access and refresh tokens in an opaque format (similar to a UUID) for internet clients, so that token contents cannot be read. This is a privacy best practice and also results in smaller cookies, which should continue to be encrypted.

If you can't use opaque tokens, an efficient token signing algorithm like ES256 can reduce the size of cookies considerably compared to RS256. You may see cookie sizes shrink by up to 50%. Eg here is a basic example ES256 JWT (about 440 bytes):

eyJhbGciOiJFUzI1NiIsImtpZCI6IjE3OTg0MzM5LTY0NmItNDYzZS1hNzI1LTAxZTMzYTE1NTgwNyJ9.eyJpc3MiOiJodHRwczovL2xvZ2luLmF1dGhzYW1wbGVzLWRldi5jb20iLCJhdWQiOiJhcGkubXljb21wYW55LmNvbSIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgaW52ZXN0bWVudHMiLCJzdWIiOiJhNmI0MDRiMS05OGFmLTQxYTItOGU3Zi1lNDA2MWRjMGJmODYiLCJtYW5hZ2VyX2lkIjoiMTAzNDUiLCJyb2xlIjoidXNlciIsImV4cCI6MTcwOTE1MTUyOH0.RkUFMuTBktET8YeR4M65LES9PME13eRe56AzP8hMhCYEGFs1eyGki-pGzqx1Gc17EHVJ9VgiA5u4j2w28uUpDg

BACKEND TOKEN STORES

I prefer to avoid these if possible, since they add complexity and could become a vulnerability. In OAuth the authorization server should do the job of storing tokens for you, as is the case when opaque tokens are used. I therefore consider it a backup option, if cookie sizes get reduced further, rather than an option that should be used by default.

JWT SOLUTION TO COMPARE AGAINST

Out of interest I have used the cookies containing tokens pattern with both JWTs and opaque tokens. You can run my Online SPA which uses AWS Cognito JWTs to view requests. It works in all mobile and desktop browsers. When I have run this in an NGINX environment though, I had to increase the default max header size of the HTTP server. This is because Cognito issues large RS256 JWTs.

2
akdombrowski On

Generally, the easiest and safest method is storing the tokens server-side (in some DB). You can create a session identifier and use that identifier as a key to look up the tokens in your database. You get a little better security because the tokens can't be leaked through the browser. Just make sure the identifier is created, stored, and used wisely. You can have a look at Session ID sections in OWASP's cheat sheet.

Not everyone is using a server and there's some care you have to take around the session identifier. And, of you're storing tokens, it may take an extra request first to your server/DB before hitting the authz server to check if the token is still valid.

You could split the tokens between access and refresh (and ID if you're using it) if you're able. You could even break it up at some interval with some pointer to the next fragment. This helps even if one of those tokens might go over that limit. This is not very easy to implement and a little more error prone having multiple pieces (there's also a ~500 total cookie limit). Need to balance risk and reward/convenience.

Another potential option, is to avoid front-loading the data request. That is, only request the data when needed instead of all at once up front. That's assuming the tokens info not pertinent to their function and you don't all of the info at once.