On Tue, Sep 26, 2017 at 8:14 AM, Michael Merickel <
mmer...@gmail.com> wrote:
>> What is the Origin header and shouldn't Pyramid/WebOb set it automatically
>> if it's becoming more important?
>
> 1) You can read the RFC about it or anything on google.
> 2) The Origin header is set by the client, not the server.
>
> If the origin matches the current domain (usually set by the host header)
> then the request is trusted by default and you do not need to modify
> anything. You have your app setup in such a way that your requests *look*
> like they are originating from another server instead of the domain hosting
> the content. Just configure your webtest requests such that the origin and
> host match and you'll be fine.
>
>> I still feel like there's a missing piece, something that needs to be
>> documented so that others don't fall into this same trap.
>
> If you would like to contribute some documentation on this once you figure
> it out I'm more than happy to review. It probably belongs in the testing
> chapter about how to use webtest. If you think webtest should set the
> origin/host the same by default then perhaps you could open an issue over
> there.
OK, I've got something that works; I'll make a cookbook page for
testing with HTTPS-only cookies. I'll try to explain it precisely now
although it's a long journey through
webtest.app, webob.request,
pyramid.csrf, and session cookies. To recap the situation:
1. The login form is CSRF-protected. (IT requirement.)
2. The app uses SessionAuthenticationPolicy and
pyramid_redis_sessions. Cookies are HTTPS-only (IT requirement.), so
setting 'redis.sessions.cookie_secure = true'. This tells the client
to send the cookie only with HTTPS requests (not HTTP).
3. All this is working fine in production.
4. The functional test logs in via a form. It uses WebTest. There is
no web server, just WebTest calling the WSGI app.
5. The test ran fine before implementing HTTPS cookies and CSRF protection.
6. HTTPS cookies broke the test, because WebTest emulates an HTTP
environment by default, so it won't transmit the cookie that indicates
the session containing the authenticated status. The login submit
fails.
7.I made the request "HTTPS" with an environ var:
``extra_environ = {"wsgi.url_scheme": "https"}``.
``apptest = webtest.testApp(app, extra_environ=extra_environ}``.
That fixed #6.
8. I implemented CSRF checking, and now the login failed because the
"origin" (the client's domain) was different was different from what
the "server" expected.
9. Troubleshooting and this list revealed two workarounds: turn off
HTTPS-only cookies and revert to HTTP, or set the de facto host as a
trusted host. (Setting 'pyramid.csrf_trusted_origins = localhost:80'.)
10. However, I didn't want to make my test configuration so different
from the real one and lose some aspect of testing. Instead I wanted to
understand the underlying problem and fix it.
11. The problem is that in the form submission request, the referer
domain was different from the current domain. I don't have access to
the request; it's internal to WebTest. I put print statements in
'pyramid.csrf' to determine what the request attributes were and what
the mismatch was. The actual domain was 'localhost' while the referer
had 'localhost:80'. It wasn't clear what code was calculating the
referer value or what it based it on. It didn't make sense because
didn't it know that 'localhost' is the same as 'localhost:80'?
12. Enlightenment came when I realized the referer was
"
https://localhost:80", which is nonsense. The default HTTPS port is
443, not 80.
13. I tried setting extra_environ "HTTP_PORT" : "443" but that didn't
work: the referer still had "
https://localhost:80".
14. I tracked down the code to the
'webob.request.BaseRequest.host_url' property. It looks first in
envvar 'HTTP_HOST' and falls back to 'SERVER_NAME' and 'SERVER_PORT'.
15. So I changed my code thus:
``extra_environ = {"HTTP_HOST": "443", "wsgi.url_scheme": "https"}
apptest.webtest.TestApp(app, extra_environ=extra_environ)''
Presto, it works!
I'm not sure if 'webtest' should be smarter, or if so exactly how. But
at least this solves this underlying problem.
Is there anything else I should do to more completely mimic an HTTPS request?
>> email to
pylons-discus...@googlegroups.com.
>> To post to this group, send email to
pylons-...@googlegroups.com.
> --
> You received this message because you are subscribed to the Google Groups
> "pylons-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to
pylons-discus...@googlegroups.com.
> To post to this group, send email to
pylons-...@googlegroups.com.
> To view this discussion on the web visit
>
https://groups.google.com/d/msgid/pylons-discuss/CAKdhhwFWJkrGFxOTkAyMDB61JkCm0%3D%3DwWONQ5V9U60D%3DAqV%3DXQ%40mail.gmail.com.
--
Mike Orr <
slugg...@gmail.com>