2014-02-24 21:30:49 -06:00
|
|
|
require_dependency 'single_sign_on'
|
2014-04-18 23:00:40 -05:00
|
|
|
|
2014-02-24 21:30:49 -06:00
|
|
|
class DiscourseSingleSignOn < SingleSignOn
|
2014-06-02 02:32:39 -05:00
|
|
|
|
2014-02-24 21:30:49 -06:00
|
|
|
def self.sso_url
|
|
|
|
SiteSetting.sso_url
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.sso_secret
|
|
|
|
SiteSetting.sso_secret
|
|
|
|
end
|
|
|
|
|
2014-02-25 16:58:30 -06:00
|
|
|
def self.generate_url(return_path="/")
|
2014-02-24 21:30:49 -06:00
|
|
|
sso = new
|
|
|
|
sso.nonce = SecureRandom.hex
|
2014-02-25 16:58:30 -06:00
|
|
|
sso.register_nonce(return_path)
|
2014-11-26 00:25:54 -06:00
|
|
|
sso.return_sso_url = Discourse.base_url + "/session/sso_login"
|
2014-02-24 21:30:49 -06:00
|
|
|
sso.to_url
|
|
|
|
end
|
|
|
|
|
2014-02-25 16:58:30 -06:00
|
|
|
def register_nonce(return_path)
|
2014-02-24 21:30:49 -06:00
|
|
|
if nonce
|
2014-02-25 16:58:30 -06:00
|
|
|
$redis.setex(nonce_key, NONCE_EXPIRY_TIME, return_path)
|
2014-02-24 21:30:49 -06:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def nonce_valid?
|
|
|
|
nonce && $redis.get(nonce_key).present?
|
|
|
|
end
|
|
|
|
|
2014-02-25 16:58:30 -06:00
|
|
|
def return_path
|
|
|
|
$redis.get(nonce_key) || "/"
|
|
|
|
end
|
|
|
|
|
2014-02-24 21:30:49 -06:00
|
|
|
def expire_nonce!
|
|
|
|
if nonce
|
|
|
|
$redis.del nonce_key
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def nonce_key
|
|
|
|
"SSO_NONCE_#{nonce}"
|
|
|
|
end
|
|
|
|
|
2015-02-25 13:40:55 -06:00
|
|
|
def lookup_or_create_user(ip_address=nil)
|
2014-05-06 08:41:59 -05:00
|
|
|
sso_record = SingleSignOnRecord.find_by(external_id: external_id)
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2014-02-27 18:48:46 -06:00
|
|
|
if sso_record && user = sso_record.user
|
2014-02-24 21:30:49 -06:00
|
|
|
sso_record.last_payload = unsigned_payload
|
|
|
|
else
|
2015-02-23 14:58:45 -06:00
|
|
|
user = match_email_or_create_user(ip_address)
|
2014-02-27 18:48:46 -06:00
|
|
|
sso_record = user.single_sign_on_record
|
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2014-02-27 18:48:46 -06:00
|
|
|
# if the user isn't new or it's attached to the SSO record we might be overriding username or email
|
|
|
|
unless user.new_record?
|
|
|
|
change_external_attributes_and_override(sso_record, user)
|
2014-02-24 21:30:49 -06:00
|
|
|
end
|
|
|
|
|
2015-05-19 11:16:02 -05:00
|
|
|
if sso_record && (user = sso_record.user) && !user.active && !require_activation
|
2014-02-25 17:28:03 -06:00
|
|
|
user.active = true
|
2014-06-02 02:32:39 -05:00
|
|
|
user.save!
|
2015-03-20 12:03:24 -05:00
|
|
|
user.enqueue_welcome_message('welcome_user') unless suppress_welcome_message
|
2014-02-25 17:28:03 -06:00
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2014-04-21 22:52:13 -05:00
|
|
|
custom_fields.each do |k,v|
|
|
|
|
user.custom_fields[k] = v
|
|
|
|
end
|
|
|
|
|
2015-02-23 14:58:45 -06:00
|
|
|
user.ip_address = ip_address
|
2014-11-26 19:39:00 -06:00
|
|
|
user.admin = admin unless admin.nil?
|
|
|
|
user.moderator = moderator unless moderator.nil?
|
|
|
|
|
2014-02-27 18:48:46 -06:00
|
|
|
# optionally save the user and sso_record if they have changed
|
|
|
|
user.save!
|
|
|
|
sso_record.save!
|
2014-02-25 17:28:03 -06:00
|
|
|
|
2014-02-24 21:30:49 -06:00
|
|
|
sso_record && sso_record.user
|
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2014-02-27 18:48:46 -06:00
|
|
|
private
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2015-02-23 14:58:45 -06:00
|
|
|
def match_email_or_create_user(ip_address)
|
2014-07-14 09:16:24 -05:00
|
|
|
user = User.find_by_email(email)
|
2014-02-27 18:48:46 -06:00
|
|
|
|
2014-06-02 02:32:39 -05:00
|
|
|
try_name = name.blank? ? nil : name
|
|
|
|
try_username = username.blank? ? nil : username
|
|
|
|
|
2014-02-27 18:48:46 -06:00
|
|
|
user_params = {
|
2015-02-23 14:58:45 -06:00
|
|
|
email: email,
|
2015-03-26 18:25:32 -05:00
|
|
|
name: try_name || User.suggest_name(try_username || email),
|
2015-02-23 14:58:45 -06:00
|
|
|
username: UserNameSuggester.suggest(try_username || try_name || email),
|
|
|
|
ip_address: ip_address
|
2014-02-27 18:48:46 -06:00
|
|
|
}
|
2014-02-24 21:30:49 -06:00
|
|
|
|
2014-06-02 02:32:39 -05:00
|
|
|
if user || user = User.create!(user_params)
|
2014-02-27 18:48:46 -06:00
|
|
|
if sso_record = user.single_sign_on_record
|
|
|
|
sso_record.last_payload = unsigned_payload
|
|
|
|
sso_record.external_id = external_id
|
|
|
|
else
|
2014-08-19 07:40:23 -05:00
|
|
|
user.create_single_sign_on_record(last_payload: unsigned_payload,
|
2014-02-27 18:48:46 -06:00
|
|
|
external_id: external_id,
|
|
|
|
external_username: username,
|
|
|
|
external_email: email,
|
|
|
|
external_name: name)
|
|
|
|
end
|
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2014-02-27 18:48:46 -06:00
|
|
|
user
|
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2014-02-27 18:48:46 -06:00
|
|
|
def change_external_attributes_and_override(sso_record, user)
|
2015-03-26 17:39:35 -05:00
|
|
|
if SiteSetting.sso_overrides_email && user.email != email
|
2014-02-27 18:48:46 -06:00
|
|
|
user.email = email
|
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2015-03-26 18:04:16 -05:00
|
|
|
if SiteSetting.sso_overrides_username &&
|
2015-03-26 18:10:53 -05:00
|
|
|
user.username != username
|
|
|
|
user.username = UserNameSuggester.suggest(username || name || email, user.username)
|
2014-02-27 18:48:46 -06:00
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2015-03-26 17:39:35 -05:00
|
|
|
if SiteSetting.sso_overrides_name && user.name != name
|
2015-05-06 22:52:26 -05:00
|
|
|
user.name = name || User.suggest_name(username.blank? ? email : username)
|
2014-02-27 18:48:46 -06:00
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
|
2015-01-28 09:47:59 -06:00
|
|
|
if SiteSetting.sso_overrides_avatar && avatar_url.present? && (
|
2015-01-28 10:52:07 -06:00
|
|
|
avatar_force_update ||
|
2014-08-19 02:49:14 -05:00
|
|
|
sso_record.external_avatar_url != avatar_url)
|
2015-01-28 09:47:59 -06:00
|
|
|
|
2014-08-19 02:49:14 -05:00
|
|
|
begin
|
2015-02-03 11:44:18 -06:00
|
|
|
tempfile = FileHelper.download(avatar_url, SiteSetting.max_image_size_kb.kilobytes, "sso-avatar", true)
|
2014-08-19 02:49:14 -05:00
|
|
|
|
2014-08-26 10:52:07 -05:00
|
|
|
ext = FastImage.type(tempfile).to_s
|
|
|
|
tempfile.rewind
|
2014-08-19 02:49:14 -05:00
|
|
|
|
2015-02-03 11:44:18 -06:00
|
|
|
upload = Upload.create_for(user.id, tempfile, "external-avatar." + ext, tempfile.size, { origin: avatar_url })
|
2014-08-19 02:49:14 -05:00
|
|
|
user.uploaded_avatar_id = upload.id
|
|
|
|
|
2014-11-20 18:36:14 -06:00
|
|
|
unless user.user_avatar
|
|
|
|
user.build_user_avatar
|
|
|
|
end
|
|
|
|
|
2014-08-19 02:49:14 -05:00
|
|
|
if !user.user_avatar.contains_upload?(upload.id)
|
|
|
|
user.user_avatar.custom_upload_id = upload.id
|
|
|
|
end
|
2015-05-19 19:43:53 -05:00
|
|
|
rescue => e
|
2014-08-19 02:49:14 -05:00
|
|
|
# skip saving, we are not connected to the net
|
2015-05-19 19:43:53 -05:00
|
|
|
Rails.logger.warn "#{e}: Failed to download external avatar: #{avatar_url}, user id #{ user.id }"
|
2014-08-19 02:49:14 -05:00
|
|
|
ensure
|
|
|
|
tempfile.close! if tempfile && tempfile.respond_to?(:close!)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-27 18:48:46 -06:00
|
|
|
# change external attributes for sso record
|
|
|
|
sso_record.external_username = username
|
|
|
|
sso_record.external_email = email
|
|
|
|
sso_record.external_name = name
|
2014-08-19 02:49:14 -05:00
|
|
|
sso_record.external_avatar_url = avatar_url
|
2014-02-27 18:48:46 -06:00
|
|
|
end
|
2014-04-15 00:53:48 -05:00
|
|
|
end
|