Consider something more lenient for cookie parsing
See original GitHub issueHello,
I have used Starlette in a handful of small services in the past few months and have been really happy with it. It’s a great project.
Last week I ran into something that I wanted to raise as a potential issue here, because it may be worth considering.
We have an application that uses Okta’s Sign-In widget for authentication (which is an OpenID Connect thing). Okta does its Oauth2 callback-redirect and they set some cookies, at least one of which is well outside the spec of HTTP cookies. Anyway, in Starlette the request.cookies
attribute ends up pretty mangled as a result.
Here’s an example of what I’m talking about using the same cookie-parsing technique in Starlette, which relies on Python’s standard library module http.cookies
:
In [1]: cookieval = """okta-oauth-nonce=validAsciiblabla; okta-oauth-state=validAsciiBlabla; okta-oauth-redirect-params={"responseType":"code","state":"somestate",
...: "nonce":"somenonce","scopes":["openid","profile","email","phone"],"urls":{"issuer":"https://subdomain.okta.com/oauth2/authServer","authorizeUrl":"https://s
...: ubdomain.okta.com/oauth2/authServer/v1/authorize","userinfoUrl":"https://subdomain.okta.com/oauth2/authServer/v1/userinfo"}}; importantCookie=importantValu
...: e; sessionCookie=importantSessionValue"""
In [2]: import http.cookies
In [3]: cookie = http.cookies.SimpleCookie()
In [4]: cookie.load(cookieval)
In [5]: list(cookie.items())
Out[5]:
[('okta-oauth-nonce', <Morsel: okta-oauth-nonce=validAsciiblabla>),
('okta-oauth-state', <Morsel: okta-oauth-state=validAsciiBlabla>)]
Notice in the example above, cookieval
contains 5 important cookies (including the session cookie set by Starlette’s SessionMiddleware
), but only two are successfully parsed by this method.
I have seen a lot of wacky stuff thrown into cookies, so it may be a good idea to provide some method to parse them more leniently in the Starlette project.
Also, out of curiosity, I took a tour through what Werkzeug is doing and they have some pretty low-level code for parsing cookies, but it does successfully parse the above:
In [6]: from werkzeug._internal import _cookie_parse_impl
In [7]: list(_cookie_parse_impl(cookieval.encode("utf-8")))
Out[7]:
[(b'okta-oauth-nonce', b'validAsciiblabla'),
(b'okta-oauth-state', b'validAsciiBlabla'),
(b'okta-oauth-redirect-params',
b'{"responseType":"code","state":"somestate","nonce":"somenonce","scopes":["openid","profile","email","phone"],"urls":{"issuer":"https://subdomain.okta.com/oauth2/authServer","authorizeUrl":"https://subdomain.okta.com/oauth2/authServer/v1/authorize","userinfoUrl":"https://subdomain.okta.com/oauth2/authServer/v1/userinfo"}}'),
(b'importantCookie', b'importantValue'),
(b'sessionCookie', b'importantSessionValue')]
In short, cookies seem to be one of those things where while there exists a spec, people have been ignoring it for a long time, and so it may be worth parsing them more leniently or offering an option to do so in the project.
Python’s http.cookies
module even has the following comment:
The module formerly strictly applied the parsing rules described in the RFC 2109 and RFC 2068 specifications. It has since been discovered that MSIE 3.0x doesn’t follow the character rules outlined in those specs and also many current day browsers and servers have relaxed parsing rules when comes to Cookie handling. As a result, the parsing rules used are a bit less strict.
Thanks for reading and for working on this project. I would be happy to help contribute back to it if I can.
For reference, here’s the RFC 6265 spec, which obsoletes the older spec referenced by the Python standard library’s http.cookies
module (it actually references an even older spec…).
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (5 by maintainers)
Top GitHub Comments
I would be happy to do that. We can use my example given above. I was hoping to find a weird-cookie dataset to try.
The best way to approach this would probably be to start by writing a failing test, and submit that as a pull request.