Matt Laux

The reason why cookies do not work with a heroku.app domain name

One of the projects I created for my portfolio during my learning journey was Sea Turtle Charter. The front-end is a very basic Next.js web application hosted on Vercel. The back-end is a Node/Express API hosted on Heroku with a PostgreSQL database.

As the front-end and back-end were hosted on two entirely separate platforms and domains, it forced me to learn a lot about web security. Here is a list of some of the issues I encountered and handled while working on this project:

  • CORS
  • Pre-flight requests
  • CSRF through double cookie submit pattern
  • Secure sessions through cookies
  • SQL injection protection
  • Rate limiting on login page
  • Various request headers
  • Hashing passwords for storage

One issue I encountered was the inability of my Heroku app to set cookies on my herokuapp.com back-end. If you have ever dealt with a separate front-end and back-end you know that any number of causes can cause issues with cookies.

As a result, it took me a while to figure out exactly what was causing the issue. Finally, I discovered that herokuapp.com is included in Mozilla's Public Suffix List.

Overview

In this article I will discuss the Mozilla Public Suffix List, why it exists, and how you can solve this issue with your web applications. This issue typically only affects the free domain names you receive from platforms as a service such as Heroku.

The majority of users using these free domain names are beginners that are most likely not aware of the Mozilla Public Suffix List. Hopefully this article can help other web developers understand the issue and how to solve it.

This issue does not just affect Heroku. It affects other platforms as a service such as Vercel and Netlify.

Table of Contents

How cookies are scoped?

Under normal operation, a website can set a cookie that is scoped to its domain or to any higher level DNS domain it belongs to. This process is dictated by the cookie's domain attribute which is included in the Set-Cookie HTTP response header.

For example let's pretend that you are on https://www.billy.bob.com/ and you are setting a cookie. You could create a cookie with the following levels of scope:

  • Just https://www.billy.bob.com/
  • All hosts ending in billy.bob.com such as appointment.billy.bob.com
  • All hosts ending in bob.com such as thomas.bob.com

This capability is allowed as typically a single entity has complete control of the bob.com domain. Not allowing cookies to be passed between any host ending in bob.com would make your jobs as web developers extremely difficult.

This cookie could not be passed to www.flyingbikes.com. This is because .com, .edu, .org, etc are considered Top-Level Domains (TLDs). Cookies cannot be scoped to a Top-Level Domain as this would be a serious security flaw. Anybody could own the flyingbikes.com domain and naturally you would not want your session cookie from billy.bob.com to be passed to a domain with an unknown owner.

What is Mozilla's Public Suffix List?

This is where the Mozilla's Public Suffix List becomes useful. With the rise of platforms as a service, there were many different web applications belonging to many different users that were all registered under heroku.app.com.

Since heroku.app.com is not a TLD, a user could theoretically set a cookie that can be retransmitted to all hosts ending in heroku.app.com. This means that cookies could be getting passed around between thousands of web applications. Clearly this is a huge security flaw.

As a result, a group of volunteers at Mozilla has created the Public Suffix List. This is a list of domains that cookies cannot be shared across. The full list can be seen here.

heroku.app.com is included on this list which is why web applications hosted on Heroku cannot set cookies to a heroku.app.com domain. Other platforms as a service such as Vercel are included on this list.

This list significantly increases cookie security. All major browsers abide by this list and even use the list for other features. If you would like to learn more, Mozilla's documentation has more information.

The solution to this issue is very straightforward. You need to add a custom domain to your web application. Your custom domain will not be included on the Public Suffix List and as a result you will be able to set your cookies properly.

If you would like to learn more about using Google Domains with Heroku check out this article.

Learn more

This is a very common issue with a simple solution. Hopefully this article helped to minimize the time and energy you spent troubleshooting why your cookies were not being set.

If you would like to learn more about the Mozilla Public Suffix List, these resources are a great place to start:

;