FEATURE: Flag to disable DiscourseConnect CSRF protection (#12356)

This is not recommended. But if you have other protections in place for CSRF mitigation, you may wish to disable Discourse's implementation. This site setting is not visible in the UI, and must be changed via the console.
This commit is contained in:
David Taylor
2021-03-11 10:38:34 +00:00
committed by GitHub
parent 593edc43c5
commit 0902e56162
3 changed files with 40 additions and 4 deletions

View File

@ -31,21 +31,37 @@ class DiscourseSingleSignOn < SingleSignOn
def register_nonce(return_path)
if nonce
if SiteSetting.discourse_connect_csrf_protection
@secure_session.set(nonce_key, return_path, expires: SingleSignOn.nonce_expiry_time)
else
Discourse.cache.write(nonce_key, return_path, expires_in: SingleSignOn.nonce_expiry_time)
end
end
end
def nonce_valid?
if SiteSetting.discourse_connect_csrf_protection
nonce && @secure_session[nonce_key].present?
else
nonce && Discourse.cache.read(nonce_key).present?
end
end
def return_path
if SiteSetting.discourse_connect_csrf_protection
@secure_session[nonce_key] || "/"
else
Discourse.cache.read(nonce_key) || "/"
end
end
def expire_nonce!
if nonce
if SiteSetting.discourse_connect_csrf_protection
@secure_session[nonce_key] = nil
else
Discourse.cache.delete nonce_key
end
end
end

View File

@ -475,6 +475,9 @@ login:
discourse_connect_overrides_website: false
discourse_connect_overrides_card_background: false
discourse_connect_not_approved_url: ""
discourse_connect_csrf_protection:
default: true
hidden: true
blocked_email_domains:
default: "mailinator.com"
type: list

View File

@ -375,10 +375,27 @@ describe DiscourseSingleSignOn do
sso = DiscourseSingleSignOn.parse(payload, secure_session: secure_session)
expect(sso.nonce_valid?).to eq true
other_session_sso = DiscourseSingleSignOn.parse(payload, secure_session: SecureSession.new("differentsession"))
expect(other_session_sso.nonce_valid?).to eq false
sso.expire_nonce!
expect(sso.nonce_valid?).to eq false
end
it "allows disabling CSRF protection" do
SiteSetting.discourse_connect_csrf_protection = false
_ , payload = DiscourseSingleSignOn.generate_url(secure_session: secure_session).split("?")
sso = DiscourseSingleSignOn.parse(payload, secure_session: secure_session)
expect(sso.nonce_valid?).to eq true
other_session_sso = DiscourseSingleSignOn.parse(payload, secure_session: SecureSession.new("differentsession"))
expect(other_session_sso.nonce_valid?).to eq true
sso.expire_nonce!
expect(sso.nonce_valid?).to eq false
end
it "generates a correct sso url" do