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

AuthTktCookieHelper includes port number in cookie domain breaking login for some browsers. #131

Closed
dokai opened this issue Feb 22, 2011 · 11 comments

Comments

@dokai
Copy link

dokai commented Feb 22, 2011

The pyramid.authentication.AuthTktCookieHelper._get_cookies() method sets the

Domain=XXX

part of the authentication cookie to a value of

cur_domain = environ.get('HTTP_HOST', environ.get('SERVER_NAME'))

In some cases the HTTP_HOST environment variable may contain a port number in addition to the domain name, e.g. www.foobar.com:80. Including the port number in the Domain part works for many browsers (Safari, Chrome, Firefox, IE) with the exception of (at least) Opera.

If the Set-Cookie headers included the port number (e.g. www.foobar.com:80) Opera will simply not send the cookies when accessing the site without the port number (e.g. www.foobar.com) which effectively makes it impossible to log in to a site with Opera.

A possible fix would be to unconditionally strip the port information in _get_cookies():

cur_domain = environ.get('HTTP_HOST', environ.get('SERVER_NAME')).split(':', 1)[0]

cheers,
Kai

@mcdonc
Copy link
Member

mcdonc commented Feb 22, 2011

I'm a little surprised this is a problem because the helper sets (at least) two cookies: one with a domain and one without.

I guess I'll have to get Opera to try it.

@dokai
Copy link
Author

dokai commented Feb 22, 2011

Yes, while testing I can see multiple Set-Cookie headers being set like you said. Nonetheless, Opera fails to send the cookies on subsequent requests.

@mcdonc
Copy link
Member

mcdonc commented Feb 22, 2011

If you change the code so it doesn't send the cookie with a domain, I presume it works, so maybe I should just add another knob to the policy.

@mcdonc
Copy link
Member

mcdonc commented Feb 22, 2011

I downloaded Opera 11.01 (for Linux) and ran the "wiki2" tutorial application from https://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src/authorization under it. In this iteration of the wiki, when you edit a page, it requires credentials (username: "editor", password: "editor"). This works in Opera for me (the login handler sets the cookie, and the cookie persists, and I can edit the page).

That said, I'd like to better understand the issue and see why it works. You don't happen to know offhand how to see request and response headers in real time in Opera do you (ala Mozilla's LiveHTTPHeaders)?

@dokai
Copy link
Author

dokai commented Feb 22, 2011

Wrt your question above, removing the cookies that set Domain allows Opera to log in. However, removing the explicit port number from the Domain value also allows Opera to function properly.

I quickly browsed the (hopefully) relevant RFC documents and didn't see anything specific in RFC2109 whether it is ok to include the port number. None of the examples do it though but in practice it works for most browsers. RFC2965 does mention ports explicitly wrt the Set-Cookie2 header but requires them to be spelled with Port=XX instead of part of the Domain=XX field. Googling on the matter shows problems related to including port numbers and examples of removing it explicitly when generating cookies.

For me, normalizing the value put in the Domain field would make more sense over adding more knobs to the policy. Should you decide to make it confirable in the policy it would be nice to update pyramid_zcml accordingly (I believe it is currently missing support for the wild_domain option also)

As for monitoring the headers with Opera, I ended up using Wireshark for lack of a better tool :)
In my case, I can reproduce this error when I access my site through Apache when it's proxied and using repoze.vhm to set a X-Vhm-Host header. In this case the environ.get('HTTP_HOST') returns something like "www.domain.com:80". Note that the X-Vhm-Host header does not contain the port number.
If I access the site directly, from http://localhost:6543/, it works in Opera without modifications.

@mcdonc
Copy link
Member

mcdonc commented Feb 22, 2011

From the code:

    # While Chrome, IE, and Firefox can cope, Opera (at least) cannot
    # cope with a port number in the cookie domain when the URL it
    # receives the cookie from does not also have that port number in it
    # (e.g via a proxy).  In the meantime, HTTP_HOST is sent with port
    # number, and neither Firefox nor Chrome do anything with the
    # information when it's provided in a cookie domain except strip it
    # out.  So we strip out any port number from the cookie domain
    # aggressively to avoid problems.  See also
    # https://github.com/Pylons/pyramid/issues/131

Closed by 0fd8eab

@mmerickel
Copy link
Member

There's a complaint that stripping out port numbers is causing problems in Opera when running on non-default ports. Anyone want to verify this?

[15:50:30] <TGEN> https://github.com/Pylons/pyramid/issues/131
[15:50:49] <TGEN> this fix breaks Opera when the app is running on a non-default port
[15:51:02] <TGEN> Opera won't accept a cookie which doesn't have the right port set
[15:51:57] <TGEN> in authentication.py, I suggest only dropping the port number if it's 80 or 443
[15:52:22] <TGEN> if ':' in cur_domain:
[15:52:39] <TGEN>    cur_domain, cur_port = cur_domain.split(':', 1)
[15:52:56] <TGEN>    if cur_port not in ['80', '443']:
[15:53:14] <TGEN>        cur_domain = cur_domain+':'+cur_port
[15:53:17] <TGEN>    else:
[15:53:31] <TGEN>        pass #nm, no need for else
[15:53:59] <TGEN> line 599 or thereabouts
[15:54:19] <TGEN> too lazy to get a github account, fork, commit change, add pullup request ;))

@mmerickel mmerickel reopened this Nov 16, 2011
@mcdonc
Copy link
Member

mcdonc commented Nov 16, 2011

this symtpom seems in 100% direct opposition to the original bug report.

@nsergey
Copy link

nsergey commented Jan 11, 2012

When I tried to check my site look in all browsers, I faced authentication problem with last Opera 11.60 (1185) win32.

The site url was http:\127.0.0.1:6544
Opera fails to send back 'auth_tkt' cookie although successfully send 'session' cookie. I tried to apply all solutions from this thread, but they don't work.
The problem is that Opera saves 'auth_tkt' cookie as sent from '127.0.0.1.local' domain.
I've changed url to http:\localhost:6544\ and then Opera started to work fine.
Hope this helps in some case.

@ghost
Copy link

ghost commented Mar 10, 2013

I dug into RFCs out of curiosity.

RFC 6265 states that cookies for a given host are shared across all the ports on that host. Furthermore the definition for the Domain attribute talks solely about FQDN or IP. Most likely one shouldn't usually set the port.

Opera apparently has stricter same-origin policy than other browsers. It is compliant to the RFC, but causes the noted side effect.

@tomster
Copy link
Member

tomster commented Aug 15, 2013

+1 on @Cuidightheach

@tomster tomster closed this as completed Aug 15, 2013
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

5 participants