9

I have a site running Django 1.6 using a custom authentication backend (CoSign). Authentication works, but to log out I need to delete a cookie.

This is the cookie before logging out, using Firebug:

  • Name: cookie_name
  • Domain: cookie_domain
  • Path: /
  • Expires: Session
  • Security: Secure

Here is my logout view:

from django.contrib.auth.views import logout as django_logout

def logout(request):
    if request.user.is_authenticated():
        response = django_logout(
                       request,
                       next_page=reverse("logout-confirmation")
                   )
        response.delete_cookie(
            'cookie_name',
            domain="cookie_domain"
        )
        return response
    else:
        messages.add_message(
            request,
            messages.ERROR,
            "You can't log out if you aren't logged "
            "in first!"
        )
        return HttpResponseRedirect(reverse("frontpage"))

cookie_name and cookie_domain in my code match the actual name and domain of the cookie.

Here are the response headers of the logout view:

Connection: "close"
Content-Length: "0"
Set-Cookie: "{{ cookie_name }}=; Domain={{ cookie_domain }}; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/sessionid=25lysb3tzhozv464mrgg08uqz100ur39; expires=Mon, 15-Sep-2014 19:07:22 GMT; httponly; Max-Age=1209600; Path=/"
Vary: "Cookie"

After going to my logout view, however, the cookie still exists! Can anyone shed some light on why this happens?

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
tao_oat
  • 1,011
  • 1
  • 15
  • 33

4 Answers4

5

I fixed this by using set_cookie() with a manually entered expiry date, rather than delete_cookie(). Additionally, if I set the domain in Django, it prefixed a period which meant that it didn't match the existing cookie. I didn't enter a domain and it used the default, which worked.

tao_oat
  • 1,011
  • 1
  • 15
  • 33
1

You can get around this problem by expiring the cookie like this:

response = django_logout(request,
                             next_page=reverse("logout-confirmation"))

response.set_cookie('cookie_name', domain="cookie_domain", max_age_seconds=1)

return response

The code above will expire your cookie after one second. This will ensure that before response reaches browser, 'cookie_name' would have expired.

mastov
  • 2,942
  • 1
  • 16
  • 33
AJNinja
  • 140
  • 1
  • 15
0

You are not returning response you construct for deleting cookie. Instead, you are returning new HttpResponseRedirect object. This is the response being served to the browser.

Do not return HttpResponseRedirect, but return response created with django_logout().

Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
  • I edited the code like you said and updated the question. Unfortunately, the issue persists! – tao_oat Sep 01 '14 at 18:57
  • Can you also give raw HTTP response output from Network tab in your web browser? Preferably, HTTP response headeres to unset the cookies? Might be somekind of cookie path issue, or just a typo in cookie name. – Mikko Ohtamaa Sep 01 '14 at 18:58
  • Yes, I added them. I haven't posted the actual cookie name and domain but I've triple-checked and they match. It seems that the Set-Cookie header has more than one path. – tao_oat Sep 01 '14 at 19:05
  • Looks like there is come `Set-Cookie` header corruption? It gets expires etc. twice if I read the output correctly. – Mikko Ohtamaa Sep 01 '14 at 19:28
  • Maybe it's the problem with `Path` which is not the same as when you do `set_cookie()` https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpResponse.delete_cookie – Mikko Ohtamaa Sep 01 '14 at 19:29
  • It's strange. The cookie was set by the custom authentication backend, so I didn't use `set_cookie()` - but it looks like the path is the default of `/`. I'll update if I resolve this. – tao_oat Sep 02 '14 at 11:18
  • No, it doesn't look like it's header corruption. Firefox's Network Monitor manages to understand that Set-Cookie is simply trying to set two different cookies. [This](http://i.imgur.com/FgjjNRO.png) is the header, and [this](http://i.imgur.com/cNz5jEn.png) is the cookie that doesn't get deleted. – tao_oat Sep 04 '14 at 16:09
0

I couldn't delete the cookies set by response.cookies[] while I could delete the cookies set by response.set_cookie() as shown below. *You can see my question and my answer explaining the difference between response.set_cookie() and response.cookies[]:

# "my_app1/views.py"

from django.http import HttpResponse

def test(request):
    response = HttpResponse('Test')
    response.set_cookie('first_name', 'John') # Here
    response.cookies['last_name'] = 'Smith' # Here
    return response
# "my_app1/views.py"

from django.http import HttpResponse

def test(request):
    response = HttpResponse('Test')
    response.delete_cookie('first_name') # Deleted
    response.delete_cookie('last_name') # Undeleted
    return response
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129