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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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
@secure_session.set(nonce_key, return_path, expires: SingleSignOn.nonce_expiry_time)
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?
nonce && @secure_session[nonce_key].present?
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
@secure_session[nonce_key] || "/"
if SiteSetting.discourse_connect_csrf_protection
@secure_session[nonce_key] || "/"
else
Discourse.cache.read(nonce_key) || "/"
end
end
def expire_nonce!
if nonce
@secure_session[nonce_key] = nil
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