From 8f414390cc72da90e9a450a2127acaea247e3dda Mon Sep 17 00:00:00 2001 From: Robert Paprocki Date: Tue, 31 May 2016 13:41:38 -0700 Subject: Implement support for SameSite attribute SameSite is an update to RFC6265, allowing servers to assert that user agents should not send certain cookies along with cross-site requests. See: https://tools.ietf.org/html/draft-west-first-party-cookies-07 --- README.md | 3 ++- lib/resty/cookie.lua | 13 +++++++++++++ t/sanity.t | 47 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5ac833d..3248285 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Synopsis key = "Name", value = "Bob", path = "/", domain = "example.com", secure = true, httponly = true, expires = "Wed, 09 Jun 2021 10:18:14 GMT", max_age = 50, - extension = "a4334aebaec" + samesite = "Strict", extension = "a4334aebaec" }) if not ok then ngx.log(ngx.ERR, err) @@ -122,6 +122,7 @@ syntax: ok, err = cookie_obj:set({ secure = true, httponly = true, expires = "Wed, 09 Jun 2021 10:18:14 GMT", max_age = 50, + samesite = "Strict", extension = "a4334aebaec" }) ``` diff --git a/lib/resty/cookie.lua b/lib/resty/cookie.lua index 11d435f..b61877e 100644 --- a/lib/resty/cookie.lua +++ b/lib/resty/cookie.lua @@ -8,6 +8,7 @@ local sub = string.sub local format = string.format local log = ngx.log local ERR = ngx.ERR +local WARN = ngx.WARN local ngx_header = ngx.header local EQUAL = byte("=") @@ -136,6 +137,17 @@ local function bake(cookie) if cookie["max-age"] then cookie.max_age = cookie["max-age"] end + + if (cookie.samesite) then + local samesite = cookie.samesite + + -- if we dont have a valid-looking attribute, ignore the attribute + if (samesite ~= "Strict" and samesite ~= "Lax") then + log(WARN, "SameSite value must be 'Strict' or 'Lax'") + cookie.samesite = nil + end + end + local str = cookie.key .. "=" .. cookie.value .. (cookie.expires and "; Expires=" .. cookie.expires or "") .. (cookie.max_age and "; Max-Age=" .. cookie.max_age or "") @@ -143,6 +155,7 @@ local function bake(cookie) .. (cookie.path and "; Path=" .. cookie.path or "") .. (cookie.secure and "; Secure" or "") .. (cookie.httponly and "; HttpOnly" or "") + .. (cookie.samesite and "; SameSite=" .. cookie.samesite or "") .. (cookie.extension and "; " .. cookie.extension or "") return str end diff --git a/t/sanity.t b/t/sanity.t index 952b81e..cb52ae8 100644 --- a/t/sanity.t +++ b/t/sanity.t @@ -5,7 +5,7 @@ use Cwd qw(cwd); repeat_each(2); -plan tests => repeat_each() * (blocks() * 3 + 4); +plan tests => repeat_each() * (blocks() * 3 + 6); my $pwd = cwd(); @@ -53,8 +53,6 @@ Cookie: SID=31d4d96e407aad42; lang=en-US SID => 31d4d96e407aad42 lang => en-US - - === TEST 2: sanity 2 --- http_config eval: $::HttpConfig --- config @@ -188,7 +186,7 @@ SID => foo key = "Name", value = "Bob", path = "/", domain = "example.com", secure = true, httponly = true, expires = "Wed, 09 Jun 2021 10:18:14 GMT", max_age = 50, - extension = "a4334aebaec" + samesite = "Strict", extension = "a4334aebaec" }) if not ok then ngx.log(ngx.ERR, err) @@ -202,7 +200,7 @@ GET /t --- no_error_log [error] --- response_headers -Set-Cookie: Name=Bob; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Max-Age=50; Domain=example.com; Path=/; Secure; HttpOnly; a4334aebaec +Set-Cookie: Name=Bob; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Max-Age=50; Domain=example.com; Path=/; Secure; HttpOnly; SameSite=Strict; a4334aebaec --- response_body Set cookie @@ -307,3 +305,42 @@ GET /t --- raw_response_headers_unlike: Set-Cookie: Name=Bob; Path=/\r\nSet-Cookie: Age=20\r\nSet-Cookie: Name=Bob; Path=/ --- response_body Set cookie + + +=== TEST 9: set cookie with invalid SameSite attribute +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua ' + local ck = require "resty.cookie" + local cookie, err = ck:new() + if not cookie then + ngx.log(ngx.ERR, err) + return + end + + local ok, err = cookie:set({ + key = "Name", value = "Bob", path = "/", + domain = "example.com", secure = true, httponly = true, + expires = "Wed, 09 Jun 2021 10:18:14 GMT", max_age = 50, + samesite = "blahblah", extension = "a4334aebaec" + }) + if not ok then + ngx.log(ngx.ERR, err) + return + end + ngx.say("Set cookie") + '; + } +--- request +GET /t +--- no_error_log +[error] +--- error_log +SameSite value must be 'Strict' or 'Lax' +--- response_headers +Set-Cookie: Name=Bob; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Max-Age=50; Domain=example.com; Path=/; Secure; HttpOnly; a4334aebaec +--- response_body +Set cookie + + -- cgit v1.2.3-54-g00ecf