Search code examples
reactjsexpresscorsmern

Express Backend/React Frontend - Mobile Browser Cross-Site Issue


I have a MERN app where the backed and frontend are deployed separately. I have CORS configured properly and state management with RTK Query. I'm using an auth token with a refresh token rotation. When the user logs in, they can check the "Trust this device" box and a "persist" flag is set in localstorage. In theory, if the user refreshes (which I know is unlikely in an SPA), the app pulls the auth token if there is one and if not, uses the refresh token to get a new auth token. If validated, they stay logged in. This works perfectly for Edge, Chrome, and Firefox desktop browsers. But for some reason, it's not working on mobile browsers.

I have an iPhone, but no Mac so I can't do remote logging. I found that it works for Safari, but that's it. After some toying, I found in Chrome that if I turned on 'Allow Cross-website Tracking', it suddenly worked. I cannot figure out why or how I set up my process correctly to not require that because I can't assume my users will know to do that. I have made sure that my origins are listed in my CORS and I know it's working because of the desktop browsers not giving errors.

Here's my CORS setup

app.use(cors(corsOptions))
import allowedOrigins from './allowedOrigins.js'

const corsOptions = {
  origin: (origin, callback) => {
    if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  },

  credentials: true,
  optionsSuccessStatus: 200,
}

export default corsOptions

Here's my cookies

// Create secure cookie with RefreshToken
  res.cookie('jwt', refreshToken, {
    httpOnly: true, //accessible only by web server
    secure: true, //https
    sameSite: 'None', //cross-site cookie
    maxAge: 30 * 24 * 60 * 60 * 1000, //cookie expiry: set to match rT
  })

I understand my cookies are set to SameSite none which makes them inherently a cross-site cookie, but how do I avoid that if the server is deployed separately from the frontend?


Solution

  • For anyone else having this trouble, after much reading I was able to fix it. Turns out that if you host your backend and frontend separately on a site that's registered in the Public Suffix List, any subdomains are seen as cross-site. The only way to fix this is to register your own domain name and add a subdomain for the server.

    I used Google Domains as they're cheap and extremely easy to setup, but this fixed my problem.