functions-samples icon indicating copy to clipboard operation
functions-samples copied to clipboard

Safari does not include cookies in JSONP requests

Open leonrinkel opened this issue 5 years ago • 8 comments

How to reproduce these conditions

Sample name or URL where you found the bug

firebase/functions-samples/spotify-auth, but the other auth examples may be affected too.

Failing Function code used (including require/import commands at the top)

spotify-auth/functions/index.js

const functions = require('firebase-functions');
const cookieParser = require('cookie-parser');
[...]
exports.token = functions.https.onRequest((req, res) => {
  try {
    cookieParser()(req, res, () => {
      console.log('Received verification state:', req.cookies.state);
      console.log('Received state:', req.query.state);
      if (!req.cookies.state) {
        throw new Error('State cookie not set or expired. Maybe you took too long to authorize. Please try again.');
      } else if (req.cookies.state !== req.query.state) {
        throw new Error('State validation failed');
      }
[...]

Steps to set up and reproduce

Setup the Spotify-auth example and use Safari (Version 12.0 14606.1.36.1.9) to test it.

Debug output

Errors in the console logs

State cookie not set or expired. Maybe you took too long to authorize. Please try again.

The req.cookies object is empty.

Expected behavior

No exception.

Actual behavior

As far as I can see, Safari does not include cookies in JSONP request. It works fine in Chrome though.

leonrinkel avatar Nov 05 '18 23:11 leonrinkel

XHR request do not work neither ☹️ I am now redirecting the whole popup to a firebase function and then passing the token back to the app via window.postMessage(). Although it works fine I'm not sure wether or not this is the right way to do it 🤔

leonrinkel avatar Nov 06 '18 16:11 leonrinkel

XHR request do not work neither ☹️ I am now redirecting the whole popup to a firebase function and then passing the token back to the app via window.postMessage(). Although it works fine I'm not sure wether or not this is the right way to do it 🤔

Can you share your solution, is it still working for you?

chenlevy avatar Apr 10 '19 06:04 chenlevy

same, looks nobody care this .

geminiyellow avatar May 10 '19 08:05 geminiyellow

I also have this issue but why noone offers a solution or help here?

jimmykane avatar Jun 03 '19 20:06 jimmykane

Same issue, with linked in sample. Can someone post a workaround as it stops PWA working on iOS.

LateralKevin avatar Jul 02 '19 00:07 LateralKevin

Same problem here in Chrome. I got the error: "Error in the token Function: Error: State cookie not set or expired. Maybe you took too long to authorize. Please try again."

Log: Received verification state: undefined

fabio-C avatar Feb 26 '21 11:02 fabio-C

I think I was finally able to solve this after poking around multiple tickets/PRs.

My solution ended up using code from: #826 #849 #852

The basic rundown:

  1. Change the req.cookies.state to be req.cookies.__session across the files as seen in these updated files
  2. Update the res.cookie object to be
    res.cookie('__session', state.toString(), {
      maxAge: 3600000,
      secure: true,
      httpOnly: true,
      SameSite: 'none'
    });

(note we changed res.cookies('state'... to be res.cookies('__session'... from step 1), also note this comment

  1. Updated my hosting rewrites to support calling the functions like:
// in firebase.json
    "public": "public",
    "rewrites": [
      {
        "source": "/redirect",
        "function": "redirect"
      },
      {
        "source": "/token",
        "function": "token"
      }
    ]

Note, I don't know if this is the secure/best/optimal way. I attempted each of these on their own and then started combining them to see what worked.

kevinguebert avatar Apr 21 '21 14:04 kevinguebert

@kevinguebert You're a godsend!

MehediH avatar Dec 12 '21 17:12 MehediH