From 94af9c6bdd808c86dba667b63e3810f0c65224f7 Mon Sep 17 00:00:00 2001 From: Maximilian Tagher Date: Sun, 25 Jan 2015 22:11:04 -0800 Subject: [PATCH 1/2] Move yesod-test to using the term "token" instead of nonce. Addresses part #1 of #914 --- yesod-test/README.md | 2 +- yesod-test/Yesod/Test.hs | 40 +++++++++++++++++++++++++++++----------- yesod-test/test/main.hs | 2 +- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/yesod-test/README.md b/yesod-test/README.md index f17be004..147fa4d0 100644 --- a/yesod-test/README.md +++ b/yesod-test/README.md @@ -50,7 +50,7 @@ This is the helloworld and kitchen sink. In this case for testing a yesod app. -- Performs the post using the current page to extract field values: post "url/to/post/to" $ do - addNonce -- Add the _nonce field with the currently shown value + addToken -- Add the CSRF _token field with the currently shown value -- Lookup field by the text on the labels pointing to them. byLabel "Email:" "gustavo@cerati.com" diff --git a/yesod-test/Yesod/Test.hs b/yesod-test/Yesod/Test.hs index 74dff8d9..b7172418 100644 --- a/yesod-test/Yesod/Test.hs +++ b/yesod-test/Yesod/Test.hs @@ -16,9 +16,9 @@ visited page. You can perform assertions on the content of HTML responses, using CSS selectors to explore the document more easily. You can also easily build requests using forms present in the current page. -This is very useful for testing web applications built in yesod, for example, -where your forms may have field names generated by the framework or a randomly -generated nonce value. +This is very useful for testing web applications built in yesod for example, +were your forms may have field names generated by the framework or a randomly +generated '_token' field. Your database is also directly available so you can use 'runDB' to set up backend pre-conditions, or to assert that your session is having the desired effect. @@ -40,7 +40,7 @@ module Yesod.Test -- * Making requests -- | You can construct requests with the 'RequestBuilder' monad, which lets you -- set the URL and add parameters, headers, and files. Helper functions are provided to - -- lookup fields by label and to add the current nonce value from your forms. + -- lookup fields by label and to add the current CSRF token from your forms. -- Once built, the request can be executed with the 'request' method. -- -- Convenience functions like 'get' and 'post' build and execute common requests. @@ -73,6 +73,8 @@ module Yesod.Test -- -- In order to prevent your forms from being rejected in tests, use one of -- these functions to add the nonce to your request. + , addToken + , addToken_ , addNonce , addNonce_ @@ -553,6 +555,16 @@ fileByLabel label path mime = do name <- nameFromLabel label addFile name path mime +-- | An alias for 'addToken_'. +addNonce_ :: Query -> RequestBuilder site () +addNonce_ = addToken_ +{-# DEPRECATED addNonce_ "Use 'addToken_' instead; 'addNonce_' will be removed in the next major version. Reasoning: Yesod's CSRF tokens are not actually nonces (one-time values), so yesod-form moved to calling them tokens instead. yesod-test is now using the word token as well. See https://github.com/yesodweb/yesod/issues/914 for details." #-} + +-- | An alias for 'addToken'. +addNonce :: RequestBuilder site () +addNonce = addToken +{-# DEPRECATED addNonce "Use 'addToken' instead; 'addNonce' will be removed in the next major version. Reasoning: Yesod's CSRF tokens are not actually nonces (one-time values), so yesod-form moved to calling them tokens instead. yesod-test is now using the word token as well. See https://github.com/yesodweb/yesod/issues/914 for details." #-} + -- | Lookup a _token form field and add its value to the params. -- Receives a CSS selector that should resolve to the form element containing the nonce. -- @@ -560,17 +572,23 @@ fileByLabel label path mime = do -- -- > request $ do -- > addNonce_ "#formID" -addNonce_ :: Query -> RequestBuilder site () -addNonce_ scope = do +addToken_ :: Query -> RequestBuilder site () +addToken_ scope = do matches <- htmlQuery' rbdResponse $ scope <> "input[name=_token][type=hidden][value]" case matches of - [] -> failure $ "No nonce found in the current page" + [] -> failure $ "No CSRF token found in the current page" element:[] -> addPostParam "_token" $ head $ attribute "value" $ parseHTML element - _ -> failure $ "More than one nonce found in the page" + _ -> failure $ "More than one CSRF token found in the page" --- | For responses that display a single form, just lookup the only nonce available. -addNonce :: RequestBuilder site () -addNonce = addNonce_ "" +-- | Lookup a _token form field and add its value to the params. +-- Receives a CSS selector that should resolve to the form element containing the nonce. +-- +-- ==== __Examples__ +-- +-- > request $ do +-- > addNonce_ "#formID" +addToken :: RequestBuilder site () +addToken = addToken_ "" -- | Perform a POST request to @url@. -- diff --git a/yesod-test/test/main.hs b/yesod-test/test/main.hs index 2bd6067d..be5363e1 100644 --- a/yesod-test/test/main.hs +++ b/yesod-test/test/main.hs @@ -122,7 +122,7 @@ main = hspec $ do setUrl ("/form" :: Text) byLabel "Some Label" "12345" fileByLabel "Some File" "test/main.hs" "text/plain" - addNonce + addToken statusIs 200 bodyEquals "12345" yit "finding html" $ do From e26f6f5fbef4bc3d4309b824f4d8182f2193bbe3 Mon Sep 17 00:00:00 2001 From: Maximilian Tagher Date: Tue, 27 Jan 2015 19:55:36 -0800 Subject: [PATCH 2/2] Update API documentation to take the nonce/token switchover into account. --- yesod-test/Yesod/Test.hs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/yesod-test/Yesod/Test.hs b/yesod-test/Yesod/Test.hs index b7172418..a6ec7991 100644 --- a/yesod-test/Yesod/Test.hs +++ b/yesod-test/Yesod/Test.hs @@ -16,9 +16,9 @@ visited page. You can perform assertions on the content of HTML responses, using CSS selectors to explore the document more easily. You can also easily build requests using forms present in the current page. -This is very useful for testing web applications built in yesod for example, -were your forms may have field names generated by the framework or a randomly -generated '_token' field. +This is very useful for testing web applications built in yesod, for example, +where your forms may have field names generated by the framework or a randomly +generated CSRF token input. Your database is also directly available so you can use 'runDB' to set up backend pre-conditions, or to assert that your session is having the desired effect. @@ -66,13 +66,13 @@ module Yesod.Test , byLabel , fileByLabel - -- *** Nonces + -- *** CSRF Tokens -- | In order to prevent CSRF exploits, yesod-form adds a hidden input -- to your forms with the name "_token". This token is a randomly generated, - -- per-session value called a /nonce/. + -- per-session value. -- -- In order to prevent your forms from being rejected in tests, use one of - -- these functions to add the nonce to your request. + -- these functions to add the token to your request. , addToken , addToken_ , addNonce @@ -565,13 +565,13 @@ addNonce :: RequestBuilder site () addNonce = addToken {-# DEPRECATED addNonce "Use 'addToken' instead; 'addNonce' will be removed in the next major version. Reasoning: Yesod's CSRF tokens are not actually nonces (one-time values), so yesod-form moved to calling them tokens instead. yesod-test is now using the word token as well. See https://github.com/yesodweb/yesod/issues/914 for details." #-} --- | Lookup a _token form field and add its value to the params. --- Receives a CSS selector that should resolve to the form element containing the nonce. +-- | Lookups the hidden input named "_token" and adds its value to the params. +-- Receives a CSS selector that should resolve to the form element containing the token. -- -- ==== __Examples__ -- -- > request $ do --- > addNonce_ "#formID" +-- > addToken_ "#formID" addToken_ :: Query -> RequestBuilder site () addToken_ scope = do matches <- htmlQuery' rbdResponse $ scope <> "input[name=_token][type=hidden][value]" @@ -580,13 +580,12 @@ addToken_ scope = do element:[] -> addPostParam "_token" $ head $ attribute "value" $ parseHTML element _ -> failure $ "More than one CSRF token found in the page" --- | Lookup a _token form field and add its value to the params. --- Receives a CSS selector that should resolve to the form element containing the nonce. +-- | For responses that display a single form, just lookup the only CSRF token available. -- -- ==== __Examples__ -- -- > request $ do --- > addNonce_ "#formID" +-- > addToken addToken :: RequestBuilder site () addToken = addToken_ "" @@ -712,7 +711,7 @@ addRequestHeader header = ST.modify $ \rbd -> rbd -- ==== __Examples__ -- -- > request $ do --- > addNonce +-- > addToken -- > byLabel "First Name" "Felipe" -- > setMethod "PUT" -- > setUrl NameR