Skip to content

Commit

Permalink
[#3858] Send password changes to the SSO Server.
Browse files Browse the repository at this point in the history
  • Loading branch information
edavis10 committed Apr 22, 2010
1 parent 22380df commit ee0c540
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 5 deletions.
14 changes: 11 additions & 3 deletions app/models/auth_source_sso.rb
Expand Up @@ -22,15 +22,19 @@ def authenticate(login, password)
end
end

def update_external(user)
def update_external(user, non_attributes={})
if user.changes.keys.include?('login')
sso_account = user.changes['login'].first # use old value
else
sso_account = user.login
end

attributes = user.attributes.merge(non_attributes).symbolize_keys

if connect_to_sso_server && user_present_on_sso_server(sso_account)
return update_account_on_sso_server(sso_account, user.hashed_password, user.attributes.symbolize_keys)
return update_account_on_sso_server(sso_account,
attributes[:previous_password] || user.hashed_password,
attributes)
end

end
Expand All @@ -39,11 +43,15 @@ def test_connection
RestClient.get(self.host)
end

def self.allow_password_changes?
true
end

private

# Need to tidy up the data into the format that Redmine requires
def format_user_hash_for_redmine_auth_source(user_hash)
return [nil] unless user_hash
return nil unless user_hash

[
user_hash.
Expand Down
18 changes: 17 additions & 1 deletion lib/redmine_sso_client/patches/user_patch.rb
Expand Up @@ -6,16 +6,32 @@ def self.included(base)
unloadable
include InstanceMethods
before_save :update_sso_server

alias_method_chain 'check_password?'.to_sym, :caching_previous_password

end
end

module InstanceMethods
define_method('check_password_with_caching_previous_password?') {|clear_password|
@previous_password = clear_password if auth_source_id
send('check_password_without_caching_previous_password?'.to_sym, clear_password)
}

def update_sso_server
if auth_source && auth_source.is_a?(AuthSourceSso) &&
(changed != ['auth_source_id'] && changed != ['last_login_on'])
auth_source.update_external(self)
# Need to send plaintext password attributes to the server
# if they are set (e.g. during change password)
non_attributes = {}
non_attributes['previous_password'] = @previous_password if @previous_password
non_attributes['password'] = self.password if self.password
non_attributes['password_confirmation'] = self.password_confirmation if self.password_confirmation

auth_source.update_external(self, non_attributes)
end
end

end

end
Expand Down
6 changes: 5 additions & 1 deletion test/unit/auth_source_sso_test.rb
Expand Up @@ -11,6 +11,10 @@ def setup
assert_equal AuthSource, AuthSourceSso.superclass
end

should "allow password changes" do
assert AuthSourceSso.allow_password_changes?
end

context "#authenticate" do
setup do
@auth_source = AuthSourceSso.new(:name => 'SSO Test', :host => 'http://sso.example.com')
Expand Down Expand Up @@ -99,7 +103,7 @@ def setup
should "return nil" do
FakeWeb.register_uri(:post, "http://sso.example.com/login.xml", :body => '', :status => ["401", "Unauthorized"])

assert_equal [nil], @auth_source.authenticate('user', 'badpassword')
assert_equal nil, @auth_source.authenticate('user', 'badpassword')
end
end
end
Expand Down
26 changes: 26 additions & 0 deletions test/unit/lib/redmine_sso_client/patches/user_patch_test.rb
Expand Up @@ -53,8 +53,34 @@ def setup
assert !@user.save
assert_equal 'sso', @user.reload.login
end

should "allow changing passwords" do
FakeWeb.register_uri(:any, "http://sso.example.com/", :status => ["200", "Success"])
FakeWeb.register_uri(:post, "http://sso.example.com/login.xml", :status => ["200", "Success"], :body => valid_user_response)
FakeWeb.register_uri(:get, "http://sso.example.com/accounts/sso/present.xml", :body => '', :status => ["200", "Success"])
FakeWeb.register_uri(:put, "http://sso.example.com/accounts/sso.xml", :body => '', :status => ["200", "Success"])

@user.password = 'new-password'
@user.password_confirmation = 'new-password'
# TODO: need to trigger the cache for this to work.
@user.check_password?('new-password')

assert @user.save
assert @user.reload.hashed_password.blank?, "Password was cached locally"

end
end
end

context "User#check_password?" do
should 'cache the previous password into an instance variable if an auth source needs access to the cleartext password' do
@user = User.generate_with_protected!(:login => 'sso')
@auth_source = AuthSourceSso.generate!(:name => 'SSO Test', :host => 'http://sso.example.com')
@user.auth_source = @auth_source
assert_equal nil, @user.instance_variable_get('@previous_password')

@user.check_password?('a-password')
assert_equal 'a-password', @user.instance_variable_get('@previous_password')
end
end
end

0 comments on commit ee0c540

Please sign in to comment.