FEATURE: add support for same site cookies

Defaults to Lax, can be disabled or set to Strict.

Strict will only work if you require login and use SSO. Otherwise when clicking on links to your site you will appear logged out till you refresh the page.
This commit is contained in:
Sam
2017-02-23 12:01:28 -05:00
parent ad435da377
commit ea1007e954
5 changed files with 42 additions and 3 deletions

View File

@ -947,6 +947,7 @@ en:
email_custom_headers: "A pipe-delimited list of custom email headers" email_custom_headers: "A pipe-delimited list of custom email headers"
email_subject: "Customizable subject format for standard emails. See https://meta.discourse.org/t/customize-subject-format-for-standard-emails/20801" email_subject: "Customizable subject format for standard emails. See https://meta.discourse.org/t/customize-subject-format-for-standard-emails/20801"
force_https: "Force your site to use HTTPS only. WARNING: do NOT enable this until you verify HTTPS is fully set up and working absolutely everywhere! Did you check your CDN, all social logins, and any external logos / dependencies to make sure they are all HTTPS compatible, too?" force_https: "Force your site to use HTTPS only. WARNING: do NOT enable this until you verify HTTPS is fully set up and working absolutely everywhere! Did you check your CDN, all social logins, and any external logos / dependencies to make sure they are all HTTPS compatible, too?"
same_site_cookies: "Use same site cookies, they eliminate all vectors Cross Site Request Forgery on supported browsers (Lax or Strict). Warning: Strict will only work on sites that force login and use SSO."
summary_score_threshold: "The minimum score required for a post to be included in 'Summarize This Topic'" summary_score_threshold: "The minimum score required for a post to be included in 'Summarize This Topic'"
summary_posts_required: "Minimum posts in a topic before 'Summarize This Topic' is enabled" summary_posts_required: "Minimum posts in a topic before 'Summarize This Topic' is enabled"
summary_likes_required: "Minimum likes in a topic before 'Summarize This Topic' is enabled" summary_likes_required: "Minimum likes in a topic before 'Summarize This Topic' is enabled"

View File

@ -896,6 +896,14 @@ security:
force_https: force_https:
default: false default: false
shadowed_by_global: true shadowed_by_global: true
same_site_cookies:
default: Lax
type: enum
choices:
- Lax
- Strict
- Disabled
regex: '^(Lax|Strict|Disabled)$'
enable_escaped_fragments: true enable_escaped_fragments: true
allow_index_in_robots_txt: true allow_index_in_robots_txt: true
enable_noscript_support: true enable_noscript_support: true

View File

@ -162,12 +162,18 @@ class Auth::DefaultCurrentUserProvider
end end
def cookie_hash(unhashed_auth_token) def cookie_hash(unhashed_auth_token)
{ hash = {
value: unhashed_auth_token, value: unhashed_auth_token,
httponly: true, httponly: true,
expires: SiteSetting.maximum_session_age.hours.from_now, expires: SiteSetting.maximum_session_age.hours.from_now,
secure: SiteSetting.force_https secure: SiteSetting.force_https
} }
if SiteSetting.same_site_cookies != "Disabled"
hash[:same_site] = SiteSetting.same_site_cookies
end
hash
end end
def make_developer_admin(user) def make_developer_admin(user)

View File

@ -10,6 +10,9 @@ class ActionDispatch::Session::DiscourseCookieStore < ActionDispatch::Session::C
if SiteSetting.force_https if SiteSetting.force_https
cookie[:secure] = true cookie[:secure] = true
end end
unless SiteSetting.same_site_cookies == "Disabled"
cookie[:same_site] = SiteSetting.same_site_cookies
end
end end
cookie_jar(request)[@key] = cookie cookie_jar(request)[@key] = cookie
end end

View File

@ -143,10 +143,8 @@ describe Auth::DefaultCurrentUserProvider do
token.reload token.reload
expect(token.auth_token_seen).to eq(false) expect(token.auth_token_seen).to eq(false)
freeze_time 21.minutes.from_now freeze_time 21.minutes.from_now
old_token = token.prev_auth_token old_token = token.prev_auth_token
unverified_token = token.auth_token unverified_token = token.auth_token
@ -222,6 +220,29 @@ describe Auth::DefaultCurrentUserProvider do
expect(UserAuthToken.where(user_id: user.id).count).to eq(2) expect(UserAuthToken.where(user_id: user.id).count).to eq(2)
end end
it "sets secure, same site lax cookies" do
SiteSetting.force_https = false
SiteSetting.same_site_cookies = "Lax"
user = Fabricate(:user)
cookies = {}
provider('/').log_on_user(user, {}, cookies)
expect(cookies["_t"][:same_site]).to eq("Lax")
expect(cookies["_t"][:httponly]).to eq(true)
expect(cookies["_t"][:secure]).to eq(false)
SiteSetting.force_https = true
SiteSetting.same_site_cookies = "Disabled"
cookies = {}
provider('/').log_on_user(user, {}, cookies)
expect(cookies["_t"][:secure]).to eq(true)
expect(cookies["_t"].key?(:same_site)).to eq(false)
end
it "correctly expires session" do it "correctly expires session" do
SiteSetting.maximum_session_age = 2 SiteSetting.maximum_session_age = 2
user = Fabricate(:user) user = Fabricate(:user)