0

Edit: It definitely isn't actually CORS. It is like it is just ignoring my attempts to write the tokens into cookies... I am also having trouble getting it to throw an error that I can find useful... I will keep throwing darts at the wall until one makes sense.

I have a graphql-yoga server with an apollo client frontend. I am using cookie-parser on the server to store Microsoft Graph authentication tokens in the browser. I am getting an error that shows up as CORS but I can't figure out why.

Access to fetch at 'https://api.mydomain.store/' from origin 'https://mydomain.store' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Error: Network error: Failed to fetch

This is strange because I can make other queries to the server with no CORS issues. I thought it had to do with the way I was setting the options on the cookies, but I think that I am doing that correctly:

//saveCookies
function saveValuesToCookie(token: any, res: Response) {
  // Parse the identity token
  const user: any = jwt.decode(token.token.id_token);

  const isDev = process.env.NODE_ENV === 'development';
  console.log('isDev: ', isDev);

  const cookieOpts: CookieOptions = {
    domain: isDev ? 'localhost' : 'mydomain.store',
    maxAge: 1000 * 60 * 60 * 24 * 365,
    httpOnly: true,
    sameSite: isDev ? 'lax' : true,
    secure: isDev ? false : true,
  };

  // Save the access token in a cookie
  res.cookie('graph_access_token', token.token.access_token, cookieOpts);

  //save the users email to a cookie
  res.cookie('graph_user_email', user.preferred_username, cookieOpts);

  // Save the refresh token in a cookie
  res.cookie('graph_refresh_token', token.token.refresh_token, cookieOpts);

  res.cookie('graph_user_id', user.oid, cookieOpts);

  // Save the token expiration tiem in a cookie
  res.cookie(
    'graph_token_expires',
    token.token.expires_at.getTime(),
    cookieOpts
  );
}

Based on the resources I have seen so far, this seems correct with current browser rules.

So I look at where I am calling the mutation:

//apollo react authorize mutation
const AUTHORIZE_MUTATION = gql`
  mutation($code: String!) {
    authorize(code: $code) {
      id
      email
      displayName
      studentFaculty
    }
  }
`;

function AuthorizePage() {
  const router = useRouter();

  const { code } = router.query;  //grab the code from the query params

  const [authorize, { loading }] = useMutation(AUTHORIZE_MUTATION, {
    variables: { code },
    // refetchQueries: [{ query: ME_QUERY }],
    onError: (error) => {
      console.error(error);  //**this is where the CORS error originates**
      return Router.push('/');
    },
    update: (_, { data }) => {
      console.log(data);   //** never gets this far **
    },
  });

  useEffect(() => {
    if (router.query.code) {
      authorize();
    }
  }, [router.query]);

  if (loading) return <Loading />;

  return <Loading />;
}

I am at a loss. Can anyone spot what is wrong or point me towards other places to look? The hardest part for me is that the code works perfectly on localhost serving client on port 3000 and server on port 4000. I don't think this error is a genuine CORS issue because of the fact that I can make unauthenticated queries no problem.

Thanks for your time!

Jordan Rhea
  • 1,186
  • 15
  • 34
  • What’s the HTTP status code of the response? You can use the Network pane in browser devtools to check. If Chrome doesn’t show it to you, use the Network pane in Firefox devtools. Is it a 4xx or 5xx error rather than a 200 OK success response? – sideshowbarker Aug 13 '20 at 21:31
  • It has a status of '(failed)net::ERR_FAILED'. It is failing so hard it doesn't even have a number... – Jordan Rhea Aug 13 '20 at 21:35
  • I have been going through and wrapping each of the auth functions in its own try/catch I think I just found the underlying error. It is status 400: Invalid request. Request is malformed or invalid. I think that has something to do with the token that is being validated at Microsoft. I got very caught up on the CORS aspect, and I think that isn't the key... – Jordan Rhea Aug 13 '20 at 21:37
  • Yeah unfortunately the way that browsers report CORS errors is misleading. It often just masks some other error, and so can cause you to end up wasting time trying to figure out why your COR config isn’t work when in fact it is actually working but there’s some other problem — an error response, network problem, firewall issue, etc. – sideshowbarker Aug 13 '20 at 21:44
  • Given what we know so far, I guess at this point you might want to consider editing/updating the question (and title) to change the focus away from CORS and over to the details about the underlying problem. – sideshowbarker Aug 13 '20 at 21:54
  • @sideshowbarker good point! i didn't remove it from the title because the error is definitely CORS related, even if that isn't the actual error. unless you think i can clarify it better another way – Jordan Rhea Aug 13 '20 at 22:34
  • Looks good to me – sideshowbarker Aug 13 '20 at 22:37
  • ```js const cookieOpts: CookieOptions = { sameSite: isDev ? 'lax' : true, }; ``` You are passing `true` in production which is setting `SameSite=strict` on your cookie. You should not need to have different values between dev and prod here, `SameSite=Lax` is fine across the board. (Sorry - comment formatting is not great!) – rowan_m Aug 14 '20 at 10:10
  • I'd also check through https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe to validate you have got the CORS configuration correct. Moving from localhost on separate ports to separate origins may introduce changes that you need to account for in the headers. – rowan_m Aug 14 '20 at 10:12

0 Answers0