I'm writing my first Pyramid application and I'm trying to strike a balance between security and useability. My environment is Python 3.3.2, Pyramid 1.4.2, and Cherrpy 3.2.4. The Intranet application uses AuthTktAuthenticationPolicy and validates users via win32security.LogonUser.
I've also implemented csrf protection using UnencryptedCookieSessionFactoryConfig for some views. A new csrf_token is created in the forbidden_view for unauthenticated users before redirecting to the login_view. The login_view calls pyramid.session.check_csrf_token at the start of form processing. If the user's login credentials validate, a new csrf_token is created.
I have some questions with respect to best practices regarding csrf protection and bookmarks.
I've written code inside my login_view to rewrite the referrer/came_from url if it contains a csrf_token to use the newly created login csrf_token - if and only if - the user is attempting to login, has a valid application account, and their Windows login credentials have been validated via win32security.LogonUser. If I don't rewrite csrf containing urls at successful login, csrf protected bookmarked views expectedly fail.
Bookmarked views not protected via @view_config check_csrf kwarg work as expected. For example, if a user is logged out and accesses such a bookmark, they are forced to successfully login before being redirected to the chosen bookmark.
However, when a user is logged out and accesses a bookmarked view protected via @view_config check_csrf kwarg I'm seeing the following behavior (i.e. browser displays 404 Not Found):
-----
serving on
0.0.0.0:8080 view at
http://127.0.0.1:8080route matched for url
http://localhost:8080/name/tom%20jones/None/None/ALL/include-payments/prod/imgret/?csrf_token=a77f342f15d74d0bb10596a5ccf11bec00d5b708; route_name: '
view.name', path_info: '/name/tom jones/None/None/ALL/include-payments/prod/imgret/', pattern: '/name/{name}*extra', matchdict: {'extra': ('None', 'None', 'ALL', 'include-payments', 'prod', 'imgret'), 'name': 'tom jones'}, predicates: ''
debug_authorization of url
http://localhost:8080/name/tom%20jones/None/None/ALL/include-payments/prod/imgret/?csrf_token=a77f342f15d74d0bb10596a5ccf11bec00d5b708 (view name '' against context <PredicateMismatch at 0x2148998404 Not Found>): Allowed (NO_PERMISSION_REQUIRED)
debug_authorization of url
http://localhost:8080/name/tom%20jones/None/None/ALL/include-payments/prod/imgret/?csrf_token=a77f342f15d74d0bb10596a5ccf11bec00d5b708 (view name '' against context <PredicateMismatch at 0x2148998404 Not Found>): Allowed (no authorization policy in use)
-----
If I remove the @view_config check_csrf kwarg from the view used in the above trace and instead call pyramid.session.check_csrf_token on entry to the view callable, I get the behavior I was expecting (i.e. a logged out user will be redirected to the login_view where the url is rewritten (for a successful login) to contain a new csrf_token giving them access to the bookmarked view).
My questions:
1) Should I not be rewriting urls which contain csrf_tokens during a successful login to support csrf protected bookmarked views? What are the risks in doing so? Is there a better/safer way to handle csrf protected bookmarked views or is this just a bad idea to begin with? (I'm sure my users will complain if bookmarks don't work as they expect.)
2) With respect to the above trace, why is the view apparently not found when the @view_config check_csrf kwarg is used? If I remove the @view_config check_csrf kwarg from the view callable and call pyramid.session.check_csrf_token directly in the view callable (and no other changes are made), I get the behavior I'm expecting (i.e. user is redirected to the forbidden_view, which forces a login; if login is successful, the bookmarked url is rewritten with a new csrf_token, and then redirection to the bookmarked view succeeds).
3) Is it best practice to create a new csrf_token in the forbidden_view
for unauthenticated users before redirecting to the login_view, where it
is subsequently checked before processing login input?
Thank you,
Peter