2014-02-25 14:30:49 +11:00
require_dependency 'single_sign_on'
2014-04-19 12:00:40 +08:00
2014-02-25 14:30:49 +11:00
class DiscourseSingleSignOn < SingleSignOn
2014-06-02 17:32:39 +10:00
2014-02-25 14:30:49 +11:00
def self . sso_url
SiteSetting . sso_url
end
def self . sso_secret
SiteSetting . sso_secret
end
2016-04-08 11:20:01 +10:00
def self . generate_sso ( return_path = " / " )
2014-02-25 14:30:49 +11:00
sso = new
sso . nonce = SecureRandom . hex
2014-02-26 09:58:30 +11:00
sso . register_nonce ( return_path )
2014-11-26 17:25:54 +11:00
sso . return_sso_url = Discourse . base_url + " /session/sso_login "
2016-04-08 11:20:01 +10:00
sso
end
def self . generate_url ( return_path = " / " )
generate_sso ( return_path ) . to_url
2014-02-25 14:30:49 +11:00
end
2014-02-26 09:58:30 +11:00
def register_nonce ( return_path )
2014-02-25 14:30:49 +11:00
if nonce
2014-02-26 09:58:30 +11:00
$redis . setex ( nonce_key , NONCE_EXPIRY_TIME , return_path )
2014-02-25 14:30:49 +11:00
end
end
def nonce_valid?
nonce && $redis . get ( nonce_key ) . present?
end
2014-02-26 09:58:30 +11:00
def return_path
$redis . get ( nonce_key ) || " / "
end
2014-02-25 14:30:49 +11:00
def expire_nonce!
if nonce
$redis . del nonce_key
end
end
def nonce_key
" SSO_NONCE_ #{ nonce } "
end
2015-02-25 14:40:55 -05:00
def lookup_or_create_user ( ip_address = nil )
2014-05-06 14:41:59 +01:00
sso_record = SingleSignOnRecord . find_by ( external_id : external_id )
2014-04-15 15:53:48 +10:00
2014-02-27 16:48:46 -08:00
if sso_record && user = sso_record . user
2014-02-25 14:30:49 +11:00
sso_record . last_payload = unsigned_payload
else
2015-02-23 15:58:45 -05:00
user = match_email_or_create_user ( ip_address )
2014-02-27 16:48:46 -08:00
sso_record = user . single_sign_on_record
end
2014-04-15 15:53:48 +10:00
2016-06-21 11:28:58 +02:00
# ensure it's not staged anymore
user . staged = false
2014-02-27 16:48:46 -08: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-25 14:30:49 +11:00
end
2015-05-19 11:16:02 -05:00
if sso_record && ( user = sso_record . user ) && ! user . active && ! require_activation
2014-02-26 10:28:03 +11:00
user . active = true
2014-06-02 17:32:39 +10:00
user . save!
2015-03-20 17:03:24 +00:00
user . enqueue_welcome_message ( 'welcome_user' ) unless suppress_welcome_message
2014-02-26 10:28:03 +11:00
end
2014-04-15 15:53:48 +10:00
2014-04-22 13:52:13 +10:00
custom_fields . each do | k , v |
user . custom_fields [ k ] = v
end
2015-02-23 15:58:45 -05:00
user . ip_address = ip_address
2016-05-17 17:31:34 +10:00
2014-11-27 12:39:00 +11:00
user . admin = admin unless admin . nil?
user . moderator = moderator unless moderator . nil?
2014-02-27 16:48:46 -08:00
# optionally save the user and sso_record if they have changed
user . save!
2016-05-17 17:31:34 +10:00
unless admin . nil? && moderator . nil?
Group . refresh_automatic_groups! ( :admins , :moderators , :staff )
end
2014-02-27 16:48:46 -08:00
sso_record . save!
2014-02-26 10:28:03 +11:00
2014-02-25 14:30:49 +11:00
sso_record && sso_record . user
end
2014-04-15 15:53:48 +10:00
2014-02-27 16:48:46 -08:00
private
2014-04-15 15:53:48 +10:00
2015-02-23 15:58:45 -05:00
def match_email_or_create_user ( ip_address )
2016-02-24 21:57:01 +01:00
unless user = User . find_by_email ( email )
try_name = name . presence
try_username = username . presence
user_params = {
email : email ,
name : try_name || User . suggest_name ( try_username || email ) ,
username : UserNameSuggester . suggest ( try_username || try_name || email ) ,
ip_address : ip_address
}
user = User . create! ( user_params )
end
2014-02-25 14:30:49 +11:00
2016-02-24 21:57:01 +01:00
if user
2014-02-27 16:48:46 -08: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 18:10:23 +05:30
user . create_single_sign_on_record ( last_payload : unsigned_payload ,
2014-02-27 16:48:46 -08:00
external_id : external_id ,
external_username : username ,
external_email : email ,
external_name : name )
end
end
2014-04-15 15:53:48 +10:00
2014-02-27 16:48:46 -08:00
user
end
2014-04-15 15:53:48 +10:00
2014-02-27 16:48:46 -08:00
def change_external_attributes_and_override ( sso_record , user )
2015-03-27 09:39:35 +11:00
if SiteSetting . sso_overrides_email && user . email != email
2014-02-27 16:48:46 -08:00
user . email = email
end
2014-04-15 15:53:48 +10:00
2015-08-24 10:24:09 +10:00
if SiteSetting . sso_overrides_username && user . username != username && username . present?
2015-03-27 10:10:53 +11:00
user . username = UserNameSuggester . suggest ( username || name || email , user . username )
2014-02-27 16:48:46 -08:00
end
2014-04-15 15:53:48 +10:00
2015-08-24 10:24:09 +10:00
if SiteSetting . sso_overrides_name && user . name != name && name . present?
2015-05-07 13:52:26 +10:00
user . name = name || User . suggest_name ( username . blank? ? email : username )
2014-02-27 16:48:46 -08:00
end
2014-04-15 15:53:48 +10:00
2015-01-28 15:47:59 +00:00
if SiteSetting . sso_overrides_avatar && avatar_url . present? && (
2015-01-28 16:52:07 +00:00
avatar_force_update ||
2014-08-19 15:49:14 +08:00
sso_record . external_avatar_url != avatar_url )
2015-01-28 15:47:59 +00:00
2015-06-23 15:59:50 -04:00
UserAvatar . import_url_for_user ( avatar_url , user )
2014-08-19 15:49:14 +08:00
end
2014-02-27 16:48:46 -08: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 15:49:14 +08:00
sso_record . external_avatar_url = avatar_url
2014-02-27 16:48:46 -08:00
end
2014-04-15 15:53:48 +10:00
end