title: Cross domain state cookie issue for oAuth using firebase functions while on the same domain
body: <p>I am implementing a oAuth login for a user for the firebase platform. </p>
  
  <p>All works fine except if the user <strong>has</strong> <strong>disabled cross domain cookies.</strong> </p>
  
  <p>Here is what I did. </p>
  
  <ol>
  <li>From my domain/app the user gets redirected to a cloud function. </li>
  <li>The could function sets the <code>state</code> cookie and redirects the user to the oAuth provider. </li>
  <li>The user signs in to the oAuth provider and gets redirected back to another function to get the code etc. <strong>And here is the problem</strong></li>
  </ol>
  
  <p>On step 3 above the function cannot read any cookie if the user has disabled the cross domain party cookies from his browser. 
  Both functions are on the same domain as seen below in the screenshot. </p>
  
  <p><a href="https://i.stack.imgur.com/MGwkp.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/MGwkp.png" alt="enter image description here"></a></p>
  
  <p>Is there any way I can remedy this issue? Am I doing something wrong in my approach? </p>
  
  <p>I cannot understand why the 2 functions are treated as crossdomain. </p>
  
  <p><strong>Update to include more info</strong></p>
  
  <p>Request: </p>
  
  <pre><code>Request URL: https://europe-west2-quantified-self-io.cloudfunctions.net/authRedirect
  Request Method: GET
  Status Code: 302 
  Remote Address: [2a00:1450:4007:811::200e]:443
  Referrer Policy: no-referrer-when-downgrade
  </code></pre>
  
  <p><strong>Request Headers</strong> </p>
  
  <pre><code>:authority: europe-west2-quantified-self-io.cloudfunctions.net
  :method: GET
  :path: /authRedirect
  :scheme: https
  accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
  accept-encoding: gzip, deflate, br
  accept-language: en-GB,en-US;q=0.9,en;q=0.8
  cookie: signInWithService=false; state=877798d3672e7d6fa9588b03f1e26794f4ede3a0
  dnt: 1
  upgrade-insecure-requests: 1
  user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
  </code></pre>
  
  <p><strong>Response Headers</strong></p>
  
  <pre><code>alt-svc: quic=":443"; ma=2592000; v="46,43,39"
  cache-control: private
  content-encoding: gzip
  content-length: 218
  content-type: text/html; charset=utf-8
  date: Sat, 03 Aug 2019 08:55:18 GMT
  function-execution-id: c8rjc7xnvoy8
  location: https://cloudapi-oauth.suunto.com/oauth/authorize?response_type=code&amp;client_id=xxx&amp;redirect_uri=&amp;scope=workout&amp;state=1c8073866d1ffaacf2d4709090ad099872718afa
  server: Google Frontend
  set-cookie: state=1c8073866d1ffaacf2d4709090ad099872718afa; Max-Age=3600; Path=/; Expires=Sat, 03 Aug 2019 09:55:18 GMT; HttpOnly; Secure
  set-cookie: signInWithService=false; Max-Age=3600; Path=/; Expires=Sat, 03 Aug 2019 09:55:18 GMT; HttpOnly; Secure
  status: 302
  vary: Accept
  x-cloud-trace-context: 99a93680a17770f848f200a9e729b122;o=1
  x-powered-by: Express
  </code></pre>
  
  <p>After that and once the user returns from the service he authenticated against the code that parses the cookies (or the function that handles that) is: </p>
  
  <pre><code>export const authToken = functions.region('europe-west2').https.onRequest(async (req, res) =&gt; {
    const oauth2 = suuntoAppAuth();
    cookieParser()(req, res, async () =&gt; {
      try {
        const currentDate = new Date();
        const signInWithService = req.cookies.signInWithService === 'true';
        console.log('Should sign in:', signInWithService);
        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');
        }
        console.log('Received auth code:', req.query.code);
        const results = await oauth2.authorizationCode.getToken({
          code: req.query.code,
          redirect_uri: determineRedirectURI(req), // @todo fix,
        });
  
        // console.log('Auth code exchange result received:', results);
  
        // We have an access token and the user identity now.
        const accessToken = results.access_token;
        const suuntoAppUserName = results.user;
  
        // Create a Firebase account and get the Custom Auth Token.
        let firebaseToken;
        if (signInWithService) {
          firebaseToken = await createFirebaseAccount(suuntoAppUserName, accessToken);
        }
        return res.jsonp({
          firebaseAuthToken: firebaseToken,
          serviceAuthResponse: &lt;ServiceTokenInterface&gt;{
            accessToken: results.access_token,
            refreshToken: results.refresh_token,
            tokenType: results.token_type,
            expiresAt: currentDate.getTime() + (results.expires_in * 1000),
            scope: results.scope,
            userName: results.user,
            dateCreated: currentDate.getTime(),
            dateRefreshed: currentDate.getTime(),
          },
          serviceName: ServiceNames.SuuntoApp
        });
      } catch (error) {
        return res.jsonp({
          error: error.toString(),
        });
      }
    });
  });
  </code></pre>
  
  <p>The above code does not find a cookie with the name <code>state</code></p>
  
  <p>So it fails here</p>
  
  <pre><code>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');
        }
  </code></pre>
  
  <p>Did a little more search here is some more info. </p>
  
  <p>The example I based on <a href="https://github.com/firebase/functions-samples/tree/master/instagram-auth" rel="nofollow noreferrer">https://github.com/firebase/functions-samples/tree/master/instagram-auth</a> </p>
  
  <p>Looks like other users suffer from the same issue <a href="https://github.com/firebase/functions-samples/issues/569" rel="nofollow noreferrer">https://github.com/firebase/functions-samples/issues/569</a></p>
  
  <p>I opened also this issue <a href="https://github.com/firebase/firebase-functions/issues/544" rel="nofollow noreferrer">https://github.com/firebase/firebase-functions/issues/544</a></p>