django-session-security: Post-logout redirect never fires

I was planning to submit a PR here today, but I’ve hit a roadblock. Setup:

We use django_cas_ng and our users auth against a CAS SSO system. When they click the Logout link on our site, they are logged out of the site AND redirected to our campus SSO system’s logout page, which kills their ticket. This is important, especially for multi-user lab computers.

After installing django-session-security, clicking the Logout link manually still works normally. But if I let a user time out with DSS, they are logged out but they are NOT redirected to the SSO logout view. They stay on the site. In this state, the user can click the Login link again and be logged in automatically again without having to authenticate (because the CAS session ticket is still alive). That’s bad.

So I started a PR that lets the dev set a custom logout URL. If present, the middleware.py adds a simple redirect after logout():

        if delta >= timedelta(seconds=expire_seconds):
            logout(request)
            return HttpResponseRedirect(settings.LOGOUT_REDIRECT_URL)

(this is in process_request()). The problem is that the redirect never happens after timeout - the user is logged out but the page is not redirected to settings.LOGOUT_REDIRECT_URL. I don’t understand why.

If I modify it to go to the CAS logout page without performing an internal logout first:

        if delta >= timedelta(seconds=expire_seconds):
            return HttpResponseRedirect(settings.LOGOUT_REDIRECT_URL)

Then a timeout logout does redirect, but if the user then tries to go back to the site (e.g. to log in as someone else), they’re stuck in a loop eternally handing off to settings.LOGOUT_REDIRECT_URL, so they can’t access the site at all.

I can’t seem to make this work either way. Any idea what I’m missing here? It seems clear that No. 1 is what I want, but I can’t figure out why the redirect never fires.

n.b. I also have code to call django_cas_ng’s logout() function rather than Django’s, but that doesn’t affect the problem - it’s the same either way.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Comments: 62 (36 by maintainers)

Most upvoted comments

If you call logout from a view, you would normally return the response. As you can see here (links to an older version of Django because the interface recently changed), one of the possible responses conveys redirect information. As you saw, the middleware does not return the response. All it does is trigger the database-side processing for the logout.

But the “answer” isn’t to change session security because the application cannot be responsible for timing out the SSO credential… the SSO server needs to do that. Consider the simplest case:

  • User A logs into the application
  • User A closes the browser window holding the application (there’s no opportunity to redirect, even if supported)
  • User B opens a new window and goes to email

Because User A’s SSO session is still alive, User B is routed to the User A’s email. There’s nothing that session security can do to take care of this. The SSO server needs to timeout the SSO session.

The application also needs a timeout so application sessions don’t outlast the SSO sessions (by more than the timeout), but session security already handles this.

@claytondaley : It worked in the production. Thank you for the help.

@santosh9991 Did you test the PR? Did it work? If so, please let us know so we can consider merging it.

If you can’t, I’m suggesting changing the way the redirect is handled.

If this solves your issue, we may want to consider a change to session security, but I’d want you to confirm that it’s working for you first.

I don’t think the content type is what matters. I think you need to get the cookies into the request. For CSRF reasons, I’m not sure the browser will ever do so automatically. I suggest trying to replace the AJAX call with a full page redirect.

Also did you try debugging the logout view ? You could also print the request headers from there.

Yes. The SO question was suggesting that an XHR request may not carry the right headers. That seemed like the next most-obvious thing to compare. I’d look at the headers first and then the cookies. If you were missing authentication information in one of these places, it would explain your issue.

The only difference I see is xhr vs. text/html. A quick search for 403 on xhr led me to this SO question:

https://stackoverflow.com/a/36816541/1978687

I’m not sure if this is your actual problem, but it aligns with the issue you describe. If your request doesn’t include headers that identify your SSO account, there’s no way to log you out.

You need to disable the filter. You see the red filter icon:

image

It’s happening because you’ve clicked “XHR”. If you unclick that icon (XHR or the filter entirely), you should get a full history.

No logs are shown in the chrome browser when user logs out(on-click through href, Ref Fig 5 in above comments) without any issues.

You should at least see the call to URLs like (obviously using your domain/IP) djangoapp.com/logout followed by ssoserver.com/login Try this sequence (leaving preserve logs on):

  • log into your application
  • click “clear” logs image
  • click logout link in app
  • (once the browser gets to the login screen) scroll to the absolute top of your chrome network logs and screenshot

You should definitely see at least the call to djangoapp.com/logout followed by some sequence that ends at ssoserver.com/login.