From 09c9efa4068a065b45864607fd833e808a9db1fe Mon Sep 17 00:00:00 2001 From: Davide Depau <davide@rev.ng> Date: Fri, 7 Apr 2023 12:08:34 +0200 Subject: [PATCH] Apply rev.ng customizations --- lib/saml_authenticator.rb | 76 ++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/lib/saml_authenticator.rb b/lib/saml_authenticator.rb index 1cd5b1f..7d9c1c1 100644 --- a/lib/saml_authenticator.rb +++ b/lib/saml_authenticator.rb @@ -78,7 +78,7 @@ class SamlAuthenticator < ::Auth::ManagedAuthenticator want_assertions_signed: !!setting(:want_assertions_signed), logout_requests_signed: !!setting(:logout_requests_signed), logout_responses_signed: !!setting(:logout_responses_signed), - signature_method: XMLSecurity::Document::RSA_SHA1, + signature_method: XMLSecurity::Document::RSA_SHA256, }, idp_slo_session_destroy: proc do |env, session| @@ -91,9 +91,28 @@ class SamlAuthenticator < ::Auth::ManagedAuthenticator ) end + # Only match by the NameID + def match_by_email + false + end + + def match_by_username + false + end + + def is_anonymous?(email) + email.start_with?("anonymous+") && email.end_with?("@rev.ng") + end + def primary_email_verified?(auth_token) attributes = OneLogin::RubySaml::Attributes.new(auth_token.extra&.[](:raw_info) || {}) + email = attributes.single("email") + return false if is_anonymous?(email) + + email_verified = attributes.single("emailVerified") + return email_verified == "true" if attributes.include?("emailVerified") + group_attribute = setting(:groups_attribute) if setting(:validate_email_fields).present? && attributes.multi(group_attribute).present? validate_email_fields = setting(:validate_email_fields).split("|").map(&:downcase) @@ -110,12 +129,16 @@ class SamlAuthenticator < ::Auth::ManagedAuthenticator extra_data = auth.extra || {} attributes = extra_data[:raw_info] || OneLogin::RubySaml::Attributes.new + log("after_authenticate: auth: #{auth.inspect}") + log("after_authenticate: attributes: #{attributes.inspect}") + log("after_authenticate: extra_data: #{extra_data.inspect}") + log("after_authenticate: uid: #{attributes.single("uid")}, #{auth[:uid]}") + auth[:uid] = attributes.single("uid") || auth[:uid] if setting(:use_attributes_uid) uid = auth[:uid] - auth.info[:email] ||= uid if uid.to_s&.include?("@") - - auth.info[:nickname] = uid.to_s if uid && setting(:use_attributes_uid) + auth.info[:username] = attributes.single("username") + auth.info[:nickname] = attributes.single("username") auth.extra = { "raw_info" => attributes.attributes } result = super @@ -133,22 +156,31 @@ class SamlAuthenticator < ::Auth::ManagedAuthenticator result.skip_email_validation = true if setting(:skip_email_validation) - if result.user.blank? - result.username = "" if setting(:clear_username) - result.user = auto_create_account(result, uid) if setting(:auto_create_account) && - result.email_valid + email = attributes.single("email") + + if not is_anonymous?(email) + if result.user.blank? + result.username = "" if setting(:clear_username) + result.user = auto_create_account(result, uid) if setting(:auto_create_account) && + result.email_valid + else + user = result.user + sync_groups(user, attributes, info) + sync_custom_fields(user, attributes, info) + sync_moderator(user, attributes) + sync_admin(user, attributes) + sync_trust_level(user, attributes) + sync_locale(user, attributes) + end else - user = result.user - sync_groups(user, attributes, info) - sync_custom_fields(user, attributes, info) - sync_moderator(user, attributes) - sync_admin(user, attributes) - sync_trust_level(user, attributes) - sync_locale(user, attributes) + result.failed = true + result.failed_reason = "Anonymous users cannot access Discourse. " + + "Convert your account to a regular account to continue." end result.overrides_username = setting(:omit_username) result.overrides_email = setting(:sync_email) + result.overrides_name = true result end @@ -278,8 +310,8 @@ class SamlAuthenticator < ::Auth::ManagedAuthenticator def sync_moderator(user, attributes) return unless setting(:sync_moderator) - is_moderator_attribute = setting(:moderator_attribute) || "isModerator" - is_moderator = %w[1 true].include?(attributes.single(is_moderator_attribute).to_s.downcase) + roles = attributes.multi("roles") || [] + is_moderator = roles.include?("discourse-moderator") or roles.include?("discourse-admin") return if user.moderator == is_moderator @@ -290,8 +322,8 @@ class SamlAuthenticator < ::Auth::ManagedAuthenticator def sync_admin(user, attributes) return unless setting(:sync_admin) - is_admin_attribute = setting(:admin_attribute) || "isAdmin" - is_admin = %w[1 true].include?(attributes.single(is_admin_attribute).to_s.downcase) + roles = attributes.multi("roles") || [] + is_admin = roles.include?("discourse-admin") return if user.admin == is_admin @@ -369,10 +401,6 @@ class SamlAuthenticator < ::Auth::ManagedAuthenticator end def resolve_username(username, name, email, uid) - suggester_input = [username, name] - suggester_input << email if SiteSetting.use_email_for_username_and_name_suggestions - suggester_input << uid - - UserNameSuggester.suggest(*suggester_input) + username end end -- GitLab