saleor-sdk
saleor-sdk copied to clipboard
Authorization Headers are not present on page refresh
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
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.
{
"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
}
}
}
`;
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).
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