diff options
author | Will Holley <willholley@gmail.com> | 2020-01-13 19:57:19 +0000 |
---|---|---|
committer | Will Holley <willholley@gmail.com> | 2020-01-15 11:21:17 +0000 |
commit | d51ace1a9a27b986d45717be3bb15f63f9b9c836 (patch) | |
tree | 0ead752863beb13d81c4cdeb9d02c7123ff87612 | |
parent | a27713c7409160407cdc057145674ad423aa963b (diff) | |
download | couchdb-d51ace1a9a27b986d45717be3bb15f63f9b9c836.tar.gz |
Add SameSite support to auth cookie
Adds a new configuration field, `couch_httpd_auth.same_site` which
sets the `SameSite` attribute of the CouchDB auth cookie. If no
value is set (the default), no `SameSite` attribute is added.
Refs #2221
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | rel/overlay/etc/default.ini | 2 | ||||
-rw-r--r-- | src/couch/src/couch_httpd_auth.erl | 16 | ||||
-rw-r--r-- | src/couch/test/exunit/same_site_cookie_tests.exs | 44 |
4 files changed, 62 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore index 5eec70f3e..3fa860c59 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *~ .venv .DS_Store +.vscode .rebar/ .eunit/ cover/ diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini index 5fc8e0761..a301987b2 100644 --- a/rel/overlay/etc/default.ini +++ b/rel/overlay/etc/default.ini @@ -245,6 +245,8 @@ iterations = 10 ; iterations for password hashing ; secret = ; users_db_public = false ; cookie_domain = example.com +; Set the SameSite cookie property for the auth cookie. If empty, the SameSite property is not set. +; same_site = ; CSP (Content Security Policy) Support for _utils [csp] diff --git a/src/couch/src/couch_httpd_auth.erl b/src/couch/src/couch_httpd_auth.erl index 515ce6132..96de5bf3b 100644 --- a/src/couch/src/couch_httpd_auth.erl +++ b/src/couch/src/couch_httpd_auth.erl @@ -273,7 +273,7 @@ cookie_auth_cookie(Req, User, Secret, TimeStamp) -> Hash = crypto:hmac(sha, Secret, SessionData), mochiweb_cookies:cookie("AuthSession", couch_util:encodeBase64Url(SessionData ++ ":" ++ ?b2l(Hash)), - [{path, "/"}] ++ cookie_scheme(Req) ++ max_age() ++ cookie_domain()). + [{path, "/"}] ++ cookie_scheme(Req) ++ max_age() ++ cookie_domain() ++ same_site()). ensure_cookie_auth_secret() -> case config:get("couch_httpd_auth", "secret", undefined) of @@ -457,6 +457,20 @@ cookie_domain() -> _ -> [{domain, Domain}] end. + +same_site() -> + SameSite = config:get("couch_httpd_auth", "same_site", ""), + case string:to_lower(SameSite) of + "" -> []; + "none" -> [{same_site, none}]; + "lax" -> [{same_site, lax}]; + "strict" -> [{same_site, strict}]; + _ -> + couch_log:error("invalid config value couch_httpd_auth.same_site: ~p ",[SameSite]), + [] + end. + + reject_if_totp(User) -> case get_totp_config(User) of undefined -> diff --git a/src/couch/test/exunit/same_site_cookie_tests.exs b/src/couch/test/exunit/same_site_cookie_tests.exs new file mode 100644 index 000000000..bad32ada4 --- /dev/null +++ b/src/couch/test/exunit/same_site_cookie_tests.exs @@ -0,0 +1,44 @@ +defmodule SameSiteCookieTests do + use CouchTestCase + + @moduletag :authentication + + def get_cookie(user, pass) do + resp = Couch.post("/_session", body: %{:username => user, :password => pass}) + + true = resp.body["ok"] + resp.headers[:"set-cookie"] + end + + @tag config: [{"admins", "jan", "apple"}, {"couch_httpd_auth", "same_site", "None"}] + test "Set same_site None" do + cookie = get_cookie("jan", "apple") + assert cookie =~ "; SameSite=None" + end + + @tag config: [{"admins", "jan", "apple"}, {"couch_httpd_auth", "same_site", ""}] + test "same_site not set" do + cookie = get_cookie("jan", "apple") + assert cookie + refute cookie =~ "; SameSite=" + end + + @tag config: [{"admins", "jan", "apple"}, {"couch_httpd_auth", "same_site", "Strict"}] + test "Set same_site Strict" do + cookie = get_cookie("jan", "apple") + assert cookie =~ "; SameSite=Strict" + end + + @tag config: [{"admins", "jan", "apple"}, {"couch_httpd_auth", "same_site", "Lax"}] + test "Set same_site Lax" do + cookie = get_cookie("jan", "apple") + assert cookie =~ "; SameSite=Lax" + end + + @tag config: [{"admins", "jan", "apple"}, {"couch_httpd_auth", "same_site", "Invalid"}] + test "Set same_site invalid" do + cookie = get_cookie("jan", "apple") + assert cookie + refute cookie =~ "; SameSite=" + end +end |