Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible reasons why session doesn't work (for debugging user's app) #68

Closed
rishabhpoddar opened this issue Jul 14, 2021 · 5 comments
Closed

Comments

@rishabhpoddar
Copy link
Member

rishabhpoddar commented Jul 14, 2021

Please see this instead: supertokens/supertokens-core#1044

When using cookie based auth

  • No supertokens.init called
  • apiDomain set on the frontend doesn't match the actual API domain - so the interceptor is not called.
  • Access-Control-Expose-Headers not set properly - which prevents frontend from reading the id-refresh-token, which prevents setting that state on the frontend.
  • Access-Control-Expose-Headers set to * - which prevents frontend from reading the front-token, which prevents setting that state on the frontend. Even though it's star, it won't work cause of using credentials.
  • sameSite is none, but user set the cookie secure flag to false.
  • Access control allow headers not set properly, failing CORS
  • anti-csrf not being provided (either token if that is the mode, or custom header)
  • Issues with iframes
  • API and website domain do not share the same TLD (for example API is on api.example.com and website is not on *.example.com and not on example.com), so Safari will not send cookies even if sameSite is none. Switch to using header based auth.
  • See Need to find solutions to issues with third party cookies and sessions (in certain situations) supertokens-core#280
  • Access-Control-Allow-Origin set to * which prevents browser from using setCredneitials: true. And if setCrednetials is false, then cookies are not sent.
  • Imported from different recipe by mistake.
  • Custom interceptor added which messes up refresh APIs. If using axios, they should add their interceptor AFTER both addAxiosInterceptor is called and after supertokens.init is called, this way, even if they are breaking the axios interface, it will still all work
  • Cookies have secure attribute in them, but the API domain being queried is HTTP
  • User's reverse proxy has a size limit on the response payload / header (can be configured on nginx). This in turn causes the access token from not being sent to the frontend, and the frontend getting a 502 (or another 5xx) error.
  • Session being created via an API that is not called by the frontend of the user's app. This can happen in case they are using some third party auth provider that calls their API webhook directly.
  • Using node-fetch instead of browser fetch even on client side. People might be using node-fetch for server side rendering and then not realising that they are using that for client as well. Our interceptors are added to window.fetch so their node-fetch wouldn't get the interceptors added, preventing a call to the refresh API.
  • Using sveltekit's fetch instead of window.fetch
  • Calling an APi from server side rendering instead of from the client.
  • Sometimes, CORS can be a problem during development. To solve this issue, you can ask the user to disable CORS on their browser using https://alfilatov.com/posts/run-chrome-without-cors/
  • Access control allow credentials may be false preventing cookies from being sent. This can happen if the frontend interception is not happening, or if the user has manually set that header to false.
  • Session.init not called, or being called after using axios / fetch (even though interceptor is being added)
  • websiteDomain is set to 127.0.0.1 but website is being loaded on the browser using localhost (or vice versa).
  • document.cookie doesn't work. This usually happens in case of electron apps or some other browser emulation tech. In this case, we see infinite refreshes being called. To solve this, we should ask the user to pass their own cookieHandler in the init function call
  • Have a proxy in the middle of frontend and backend which strips away necessary headers like cookies. This causes weird behaviour where refresh might return unauthorised and the frontend would clear frontend set cookies, but the backend sAccessToken and stuff still remains..
  • sessionScope not correctly set yields sIRTFrontend not being set even after session refreshing returns 401 on first visit.
  • cookieDomain not correctly set which yiels access token and others not being attached to apiDomain
  • On the frontend, websiteBasePath is set to an incorrect value. This leads the auth page to navigate to some other page than what is expected
  • For domains like heroku, if the website domain and api domain are not equal or not a sub domain (disregard the .herokuapp.com common part), then same site has to be set to none. Note that this will not work on safari. Switch to using header based auth.
  • User is using another session management solution like django's built in which returns 401 causing refresh session to be called which returns 200, and then it goes in an infinite loop.
  • User is using auto generated client code (from swagger for example), which also seems to add a fetch interceptor. That fetch interceptor probably runs after ours, and if the user gives credentials: "same-origin", to the headers for that lib, the cookies won't be sent.
  • In react native the user may have either accidentally used CookieManager.clearAllCookies or they might be manually adding cookies while replacing existing ones.
  • The user has explicitly set access-control-expose-headers and their values are incorrect. Their headers override ours. This can cause an issue in which the access token and stuff gets set, but the sIRTFrontend and frontToken on the cookie don't get set.
  • The apiDomain and websiteDomain are on a shared domain (like azurewebsite.net) and the api and website are diffrent sub domains of this - but our SDK doesn't recognise that this is a shared domain and sets the cookie same site to lax, even though it should be none.
  • Changing of cookie domain value can lead to older session tokens (refresh token) still lingering around in the browser, and if that refresh token gets picked up during session refreshing, then refreshing will always fail - even for new logins. The solution is to clear all cookies in the browser.
  • If verifySession returns 403, and the response contains claimValidationErrors: id: st-ev, this means that the user needs to go through the email verification flow
  • Changing cookieDomain on the backend whilst a session exists may lead to having two sAccessTokens which will cause issues like the session not being verified correctly. The solution here is to manually clear the cookies and relogin.
  • In iOS, when you open webview in the app, and it has say, cookie like sAccessToken, and the react native app itself has header based auth, then when you make requests in the RN app to the backend, it adds the sAccessToken from the web UI cookie as well! So the request has both, the auth bearer token and the sAccessToken in it. Now, this works fine when there is an auth bearer token, as the backend SDK just uses that. However, if you log out in the RN app, and then when you try and login, the request will have just the sAccessToken. Now if that sAccessToken has expired, then the sign in API will send a 401, and the frontend wont even try and refresh cause it (correctly) thinks that the session doesn’t exist! The way to fix this would be to enforce using header based auth on the backend for mobile apps.
  • Dev stored stale access token in memory and is using that in requests instead of reading each time from storage.
  • apiBasePath does not match on the frontend and backend:
    • This can imply that the refresh cookie is set on a different path, breaking the refresh flow.
    • If the inital refresh API call (without a session) is returning a 200 instead of 404, it means that the user's backend is returning 200 for not found routes (which is strange), but it has happened before. This would then mean that the frontend prints the warning of front token is not being able to be set: Failed to retrieve local session state from cookies after a successful session refresh. This indicates a configuration error or that the browser is preventing cookie writes.
  • If the refresh API returns a 500 error -> this implies there are multiple session tokens (which happens cause of cookieDomain change), but the user has forgotten to set the olderCookieDomain config in backend session.init.
  • There was a case where the frontend was sending one sAccessToken, but the backend was getting 2 of them. This happened cause of some issue in golang, fiber framework which somehow caused cookies to be duplicated on the backend, and then our middleware saw two cookies instead of one.
  • If the user is seeing front-token change on the frontend during api request, (like the user id in it changing, or some claim changing) even though they have not made the change, the issue is usually due to caching. This can be solved by adding a header like res.setHeader('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate'); to your apis.
  • If using an API gateway, make sure to add rid,fdi-version,anti-csrf,st-auth-mode to the existing Access-Control-Allow-Headers in the API gateway settings
  • If you are seeing this error on the backend The "listener" argument must be of type function. Received an instance of Object, then see this thread: https://discord.com/channels/603466164219281420/1278371807925108791/1278371807925108791
  • If you are seeing `Failed to retrieve local session state from cookies after a successful session refresh. This indicates one of the two issues:
    • a configuration error or that the browser is preventing cookie writes.on the frontend, then it is most likely due to a misconfig of thesessionTokenFrontendDomain` (if you have set it). Either remove that config, or set it to a value that has the same top level domain as the current browser url.
    • The backend is not sending the front-token response header in the refresh API response headers. So check why that would happen.
    • The backend is sending a front-token in the refresh API response header, but the Access-Control-Expose-Headers does not contain front-token
@snipebin
Copy link

snipebin commented Aug 6, 2021

Hi there, not sure if this is the right place to inquire but I'm wondering what to do in this case:

API and website domain do not share the same TLD, and Safari will not send cookies even if sameSite is none.

i.e my web app is served on app.example.com and my API is available on api.example.com

@rishabhpoddar
Copy link
Member Author

@snipebin app.example.com and api.example.com do share the same top level domain. Therefore, it should work fine.

@rishabhpoddar
Copy link
Member Author

@rishabhpoddar
Copy link
Member Author

Appinfo config related issues

  • If the user is seeing a tenant not found error in their api calls, its likely that the apiBasePath is misconfigured (not matching). This can happen if something like /api/auth is on the frontend, and /api is on the backend. This way, the auth part of the path is considered the tenantid, which probably wont exist.
  • If using a reverse proxy that strips away part of the path, then be sure to configure apiGatewayPath on the frontend and backend

@rishabhpoddar
Copy link
Member Author

Please see supertokens/supertokens-core#1044 instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants