1

Is there anyway in django that if user has two open tabs, both logged out, then logs in in one tab, tell that he has logged in in another tab? I mean something like github that tells you you have signed in, please refresh the page.

The problem is now If I login in one tab and then in the second tab, I get csrf token missing incorrect.

Hamed Salimian
  • 791
  • 2
  • 11
  • 28

2 Answers2

1

You get csrf token missing incorrect. because when user relogins, the server generates a new csrf token to the cookie. The cookie persists across the same domain. And when you're trying to do smth on the current page, the request fails because csrf in your <form> differs from the cookie which has been changed. That's why github refreshes the page (instead of conitnuing doing request from it). Thus server will return new csrf in html to your form.

Edit:

Consider the following choices :

  • If your cookie is not readonly: . Set setInterval where you check the session which user loaded the page and current session from cookie.
  • Render 4 first characters too page and save it to a variable. Set this variable when page loads. And with every request pass the variable with headers. Add a middleware which checks if first 4 characters in headers matcher first 4 characters from cookie, and if it doesn't tell the client to refresh the page.
  • If you want to automatically detect your case, you need to frequently spam the server and ask if the session has changed. From the client you can send the old session and the new one (if session is readonly you can send like few first characters from the server).
deathangel908
  • 8,601
  • 8
  • 47
  • 81
1

I don't know exactly how github does this. But one possibility is to use a visibilitychange event handler. This will trigger when you switch tabs. The event handler can check the cookies for the current site, and determine if someone logged in another tab.

https://developer.mozilla.org/en-US/docs/Web/Events/visibilitychange

Usually tabs share no state. But two tabs have the same origin (domain name), they share cookies. In django you typically render the csrf token to the html dom with the template tag {% csrf_token %}, which means that if the current tab's csrf token was invalidated (which happens when you sign in), you must refresh the page to get a fresh token.

One way to do attach such an event listener is this:

// check cookie for `logged_in` substring (this only works for insecure cookies. Not http-only)
const isLoggedIn = () => document.cookie.includes('logged_in')

// check cookie for changes when you open this tab
const signInSpy = () => {
  document.visibilitystate === 'visible' &&
    isLoggedIn() &&
    alert('refresh, please')
}

// only attach event handler when not signed in.
document.onvisibilitychange = isLoggedIn() ? null : signInSpy

This example only works if logged_in is not a http-only cookie. For other options for communicating between tabs, see this question: Communication between tabs or windows

Håken Lid
  • 22,318
  • 9
  • 52
  • 67