testing users with webtest

27 views
Skip to first unread message

zsol...@gmail.com

unread,
Feb 8, 2021, 7:38:12 PM2/8/21
to pylons-discuss
Hi,

I'd like to use webtest to test my application's responses with an authenticated user. I tried everything with mocking, monkeypatch, etc. but couldn't figure out. I see that there is testing_securitypolicy but I have no idea how could I integrate it with webtest.

Finally I found the best resources on: https://docs.pylonsproject.org/projects/pyramid/en/master/tutorials/wiki2/tests.html, it was quite hidden. Based on this, I made the following snippet:


@pytest.fixture(scope="session")
def app():
    return main({"testing": True})

class TestApp(webtest.TestApp):
    def get_cookie(self, name, default=None):
        cookie = Cookie(
            ' '.join('%s=%s' % (c.name, c.value) for c in self.cookiejar if c.name == name)
        )
        return next(
            (m.value.decode('latin-1') for m in cookie.values()),
            default,
        )

    def get_csrf_token(self):
        return self.get_cookie('csrf_token')

    def login(self):
        body = dict(csrf_token=self.get_csrf_token(), **TEST_USER_LOGIN)
        return self.post('/login', body, status=302)


@pytest.fixture
def testapp(app):
    testapp = TestApp(app)
    testapp.set_cookie('csrf_token', 'dummy_csrf_token')
    return testapp

This works, as long as I use the following in my __init__.py
if testing:
    config.set_csrf_storage_policy(CookieCSRFStoragePolicy())


There are a few things which are confusing me here:
1. I can remove get_cookie and get_csrf_token and just hard-code 'dummy_csrf_token' into login / post(), and it still works. Am I missing something here?

2. I don't get all the CSRF behaviour here. Isn't it generated on the server side and webtest is client side only? How can it make Pyramid accept a "dummy_csrf_token" as a CSRF token? Is there some magic in CookieCSRFStoragePolicy or WebTest?

3. Do I understand right that using CookieCSRFStoragePolicy is required for webtest CSRF to work?

Thanks,
Zsolt




Michael Merickel

unread,
Feb 8, 2021, 11:43:29 PM2/8/21
to pylons-...@googlegroups.com
On Feb 8, 2021, at 18:38, zsol...@gmail.com <zsol...@gmail.com> wrote:

There are a few things which are confusing me here:
1. I can remove get_cookie and get_csrf_token and just hard-code 'dummy_csrf_token' into login / post(), and it still works. Am I missing something here?

The CookieCSRFStoragePolicy does not attempt to verify the cookie's value, it just needs the value in the submitted form request (header or body) to match the value in the cookie.

2. I don't get all the CSRF behaviour here. Isn't it generated on the server side and webtest is client side only? How can it make Pyramid accept a "dummy_csrf_token" as a CSRF token? Is there some magic in CookieCSRFStoragePolicy or WebTest?

The assumption is that no one but your domain can set cookies on your domain, so it doesn't need to be overly protected from tampering - it just needs to be a value that malicious code running on another domain can't access or set.

3. Do I understand right that using CookieCSRFStoragePolicy is required for webtest CSRF to work?

No it's not required, but it is a really simple approach. There's plenty of alternatives to grab the CSRF token in your code so that you can re-submit it in subsequent requests but they aren't as easy. The trick to any CSRF request is that it's trying to enforce a GET followed by a POST, to avoid people triggering a cross-site POST from their own domain with malicious content. So if you do a GET first, you can parse the token out of the returned form, or webtest also has APIs that can be used to submit the form without any parsing, assuming your app supports a submitted web form submitted in x-www-form-urlencoded format.

Andreas Kaiser

unread,
Feb 9, 2021, 3:30:26 AM2/9/21
to pylons-discuss

On 9 Feb 2021, at 1:38, zsol...@gmail.com wrote:

I'd like to use webtest to test my application's responses with an
authenticated user. I tried everything with mocking, monkeypatch, etc. but
couldn't figure out. I see that there is testing_securitypolicy but I have
no idea how could I integrate it with webtest.

Kotti’s test suite uses a pytest marker for running tests with an authenticated user. The webtest fixture monkey patches pyramid.authentication.AuthTktAuthenticationPolicy.unauthenticated_userid (https://github.com/Kotti/Kotti/blob/master/kotti/tests/__init__.py#L296). It can be used like this: https://github.com/Kotti/Kotti/blob/master/kotti/tests/test_functional.py#L218.

HTH,
Andreas

Reply all
Reply to author
Forward
0 new messages