saleor-sdk icon indicating copy to clipboard operation
saleor-sdk copied to clipboard

Authorization Headers are not present on page refresh

Open Sridatta19 opened this issue 3 years ago • 4 comments

The Issue

Upon authenticating, I can see -

  • CSRF token is created successfully and stored in local storage
  • access token is set to Authorization Bearer headers

But when I refresh the page, the headers are lost. Then the REFRESH_TOKEN_WITH_USER mutation fails and the user is logged out and the CSRF token is removed from local storage.

I was able to replicate this issue with the SDK version (^0.4.0-7) and react-storefront repository.

Any pointers to help resolve this issue are helpful. Thanks in advance

Sridatta19 avatar Nov 03 '21 13:11 Sridatta19

Hey @Sridatta19, the access token is not stored/persisted globally and it's only there for the duration of runtime. Instead we use a combination of CSRF token + refresh token stored inside a cookie for a fully secure authentication flow. This means on page refresh the access token is not immediately present. If mutation REFRESH_TOKEN_WITH_USER fails this will cause the session to be lost. Please check if you're not using browser mode that disables all cookies (Chrome incognito does that by default) as this will cause the cookie not to be persisted. If that's still not the case, see what the mutation failure response looks like.

jwm0 avatar Nov 18 '21 08:11 jwm0

{
    "data": {
        "tokenRefresh": {
            "__typename": "RefreshToken",
            "token": null,
            "user": null,
            "errors": [
                {
                    "__typename": "AccountError",
                    "code": "JWT_MISSING_TOKEN",
                    "field": "refreshToken",
                    "message": "Missing refreshToken"
                }
            ]
        }
    }
}

This is the response I'm receiving upon attempting to refresh the page. I'm wondering if this is happening because I'm using Saleor API v3.0.

I saw the below code snippet which represents the code used in my product but when I cross-check the Saleor V3 API, the mutation is expecting refreshToken also as an argument.

// separate mutation so the request payload is minimal when user is not needed
// used for initial authentication
export const REFRESH_TOKEN_WITH_USER = gql`
  ${accountErrorFragment}
  ${userFragment}
  mutation refreshTokenWithUser($csrfToken: String!) {
    tokenRefresh(csrfToken: $csrfToken) {
      token
      user {
        ...UserFragment
      }
      errors {
        ...AccountErrorFragment
      }
    }
  }
`;

Sridatta19 avatar Nov 25 '21 12:11 Sridatta19

The mutation allows to pass refreshToken either explicitly (as a GraphQL variable) or implicitly via a cookie. Check if cookies are being set properly on initial login (response should have a cookie header).

jwm0 avatar Dec 20 '21 12:12 jwm0

I was having the same issue and the server response comes with the cookie but the browser won't set it because the refreshToken cookie is in a between sites context and its SameSite attribute is Lax or Strict.

It happened to me because I was developing the client locally using a Heroku server and didn't allow my PC as a allowed host. I couldn't manage to allow my PC as a allowed host so I used a local server with the DEBUG config variable set to True and it worked.

You either have to set your client address in the ALLOWED_CLIENT_HOSTS config var or develop with client and server locally and set the DEBUG config variable to True

wellzenon avatar Feb 05 '22 05:02 wellzenon