8👍
First a quick bit of background, as you might find it interesting: this is partly related to the CSRF token and partly related to the session.
The way CSRF works in Django is that the same token is mirrored in both the template and the session – that’s how Django checks that incoming form data matches the user’s session and isn’t an injection from someone evil.
When you go from being logged out to logged in, you’re trading an unauthenticated session for an authenticated session, which means you get a new session — complete with a new CSRF token in the session. That session is shared across all your tabs, even ones open already and even in a browser like Chrome which has separate processes for each tab.
So, logging in on tab A gives Tab B a session cookie which no longer matches the CSRF token embedded in the page, hence Tab B throws as CSRF exception. If you refreshed Tab B after logging in on Tab A (and assuming that a logged-in user can still see a login screen), it should let you log in in again, because the refreshed page’s CSRF token will once again match the one in the session.
In terms of handling this gracefully, I suggest you add a custom 403 handler view which either shows a prettier 403 page of your own design, or — if you think it’s acceptable — redirects the user to somewhere else (but i’d check that this redirect only happens if it’s in response to a bogus login as described in your question)
The other thing to say is: the use-case you’re talking about (two tabs open) is pretty slim – I’d just go with a custom 403 page to make it prettier, rather than redirect.
If you’re interested, look at the source:
if SESSION_KEY in request.session:
if request.session[SESSION_KEY] != user.pk:
# To avoid reusing another user's session, create a new, empty
# session if the existing session corresponds to a different
# authenticated user.
request.session.flush()
else:
request.session.cycle_key()
When you start with an unauthenticated user, there’s no way that user.pk would be the same as your authenticated user’s PK, so you get a new session.
(If you log in again as the same user, you get cycle_key() called, which may actually preserve the CSRF token – I haven’t checked)
-3👍
you should do shomething like this:
def userlogin(request):
if request.method=='POST':
user = request.user
if user.is_authentificated:
return HttpResponceRedirect('some_url')
else:
#your login procedure