diff --git a/app/models/discourse_single_sign_on.rb b/app/models/discourse_single_sign_on.rb index 8de332750..e88846b61 100644 --- a/app/models/discourse_single_sign_on.rb +++ b/app/models/discourse_single_sign_on.rb @@ -80,6 +80,7 @@ class DiscourseSingleSignOn < SingleSignOn user.moderator = moderator unless moderator.nil? # optionally save the user and sso_record if they have changed + user.user_avatar.save! if user.user_avatar user.save! if bio && (user.user_profile.bio_raw.blank? || SiteSetting.sso_overrides_bio) @@ -118,11 +119,13 @@ class DiscourseSingleSignOn < SingleSignOn sso_record.last_payload = unsigned_payload sso_record.external_id = external_id else + UserAvatar.import_url_for_user(avatar_url, user) if avatar_url.present? user.create_single_sign_on_record(last_payload: unsigned_payload, external_id: external_id, external_username: username, external_email: email, - external_name: name) + external_name: name, + external_avatar_url: avatar_url) end end diff --git a/spec/controllers/session_controller_spec.rb b/spec/controllers/session_controller_spec.rb index 228769c8d..0354ff813 100644 --- a/spec/controllers/session_controller_spec.rb +++ b/spec/controllers/session_controller_spec.rb @@ -376,6 +376,63 @@ describe SessionController do end end + describe '.sso_provider' do + before do + SiteSetting.enable_sso_provider = true + SiteSetting.enable_sso = false + SiteSetting.enable_local_logins = true + SiteSetting.sso_secret = "topsecret" + + @sso = SingleSignOn.new + @sso.nonce = "mynonce" + @sso.sso_secret = SiteSetting.sso_secret + @sso.return_sso_url = "http://somewhere.over.rainbow/sso" + + @user = Fabricate(:user, password: "frogs", active: true, admin: true) + EmailToken.update_all(confirmed: true) + end + + it "successfully logs in and redirects user to return_sso_url when the user is not logged in" do + get :sso_provider, Rack::Utils.parse_query(@sso.payload) + expect(response).to redirect_to("/login") + + xhr :post, :create, login: @user.username, password: "frogs", format: :json + + location = cookies[:sso_destination_url] + # javascript code will handle redirection of user to return_sso_url + expect(location).to match(/^http:\/\/somewhere.over.rainbow\/sso/) + + payload = location.split("?")[1] + sso2 = SingleSignOn.parse(payload, "topsecret") + + expect(sso2.email).to eq(@user.email) + expect(sso2.name).to eq(@user.name) + expect(sso2.username).to eq(@user.username) + expect(sso2.external_id).to eq(@user.id.to_s) + expect(sso2.admin).to eq(true) + expect(sso2.moderator).to eq(false) + end + + it "successfully redirects user to return_sso_url when the user is logged in" do + log_in_user(@user) + + get :sso_provider, Rack::Utils.parse_query(@sso.payload) + + location = response.header["Location"] + expect(location).to match(/^http:\/\/somewhere.over.rainbow\/sso/) + + payload = location.split("?")[1] + sso2 = SingleSignOn.parse(payload, "topsecret") + + expect(sso2.email).to eq(@user.email) + expect(sso2.name).to eq(@user.name) + expect(sso2.username).to eq(@user.username) + expect(sso2.external_id).to eq(@user.id.to_s) + expect(sso2.admin).to eq(true) + expect(sso2.moderator).to eq(false) + end + end + describe '.create' do let(:user) { Fabricate(:user) } diff --git a/spec/models/discourse_single_sign_on_spec.rb b/spec/models/discourse_single_sign_on_spec.rb index 2e4c61967..63db5d0de 100644 --- a/spec/models/discourse_single_sign_on_spec.rb +++ b/spec/models/discourse_single_sign_on_spec.rb @@ -19,6 +19,12 @@ describe DiscourseSingleSignOn do sso.username = "sam" sso.name = "sam saffron" sso.external_id = "100" + sso.avatar_url = "https://cdn.discourse.org/user_avatar.png" + sso.avatar_force_update = false + sso.bio = "about" + sso.admin = false + sso.moderator = false + sso.suppress_welcome_message = false sso.require_activation = false sso.custom_fields["a"] = "Aa" sso.custom_fields["b.b"] = "B.b" @@ -31,6 +37,12 @@ describe DiscourseSingleSignOn do expect(parsed.username).to eq sso.username expect(parsed.name).to eq sso.name expect(parsed.external_id).to eq sso.external_id + expect(parsed.avatar_url).to eq sso.avatar_url + expect(parsed.avatar_force_update).to eq sso.avatar_force_update + expect(parsed.bio).to eq sso.bio + expect(parsed.admin).to eq sso.admin + expect(parsed.moderator).to eq sso.moderator + expect(parsed.suppress_welcome_message).to eq sso.suppress_welcome_message expect(parsed.require_activation).to eq false expect(parsed.custom_fields["a"]).to eq "Aa" expect(parsed.custom_fields["b.b"]).to eq "B.b"