From 194e924cb7c36eafa01b68c74774505e170e47ac Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 30 Oct 2012 12:32:10 +0100 Subject: adding in warden with a basic strategy currently failing because we are not setting the content-type header. --- users/app/controllers/application_controller.rb | 2 +- users/app/controllers/sessions_controller.rb | 16 ++------ users/config/initializers/warden.rb | 52 +++++++++++++++++++++++++ users/leap_web_users.gemspec | 1 + users/lib/leap_web_users/engine.rb | 1 + 5 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 users/config/initializers/warden.rb (limited to 'users') diff --git a/users/app/controllers/application_controller.rb b/users/app/controllers/application_controller.rb index 64e1a55..8388dda 100644 --- a/users/app/controllers/application_controller.rb +++ b/users/app/controllers/application_controller.rb @@ -4,7 +4,7 @@ class ApplicationController < ActionController::Base private def current_user - @current_user ||= User.find(session[:user_id]) if session[:user_id] + @current_user ||= env['warden'].user end helper_method :current_user diff --git a/users/app/controllers/sessions_controller.rb b/users/app/controllers/sessions_controller.rb index 4a1107d..3872866 100644 --- a/users/app/controllers/sessions_controller.rb +++ b/users/app/controllers/sessions_controller.rb @@ -6,21 +6,13 @@ class SessionsController < ApplicationController end def create - @user = User.find_by_param(params[:login]) - session[:handshake] = @user.initialize_auth(params['A'].hex) - render :json => session[:handshake] - rescue RECORD_NOT_FOUND - render :json => {:errors => {:login => ["unknown user"]}} + debugger + env['warden'].authenticate! end def update - @srp_session = session.delete(:handshake) - @user = @srp_session.authenticate!(params[:client_auth].hex) - session[:user_id] = @user.id - render :json => @srp_session - rescue WRONG_PASSWORD - session[:handshake] = nil - render :json => {:errors => {"password" => ["wrong password"]}} + debugger + env['warden'].authenticate! end def destroy diff --git a/users/config/initializers/warden.rb b/users/config/initializers/warden.rb new file mode 100644 index 0000000..bb7dc13 --- /dev/null +++ b/users/config/initializers/warden.rb @@ -0,0 +1,52 @@ +Rails.configuration.middleware.use Warden::Manager do |manager| + manager.default_strategies :secure_remote_password + manager.failure_app = SessionsController +end + +# Setup Session Serialization +class Warden::SessionSerializer + def serialize(record) + [record.class.name, record.id] + end + + def deserialize(keys) + klass, id = keys + klass.find(id) + end +end + +Warden::Strategies.add(:secure_remote_password) do + + def valid? + id && ( params['A'] || params['client_auth'] ) + end + + def authenticate! + if params['client_auth'] && session[:handshake] + validate! + else + initialize! + end + end + + protected + + def validate! + srp_session = session.delete(:handshake) + user = srp_session.authenticate(params['client_auth'].hex) + user.nil? ? fail!("Could not log in") : success!(u) + end + + def initialize! + user = User.find_by_param(id) + session[:handshake] = user.initialize_auth(params['A'].hex) + custom! [200, {}, [session[:handshake].to_json]] + rescue RECORD_NOT_FOUND + fail! "User not found" + end + + def id + params["id"] || params["login"] + end +end + diff --git a/users/leap_web_users.gemspec b/users/leap_web_users.gemspec index 6d35f63..477265e 100644 --- a/users/leap_web_users.gemspec +++ b/users/leap_web_users.gemspec @@ -18,4 +18,5 @@ Gem::Specification.new do |s| s.add_dependency "leap_web_core", LeapWeb::VERSION s.add_dependency "ruby-srp", "~> 0.1.3" + s.add_dependency "warden" end diff --git a/users/lib/leap_web_users/engine.rb b/users/lib/leap_web_users/engine.rb index 9b7545e..25c110e 100644 --- a/users/lib/leap_web_users/engine.rb +++ b/users/lib/leap_web_users/engine.rb @@ -1,6 +1,7 @@ # thou shall require all your dependencies in an engine. require "leap_web_core" require "leap_web_core/ui_dependencies" +require "warden" require "ruby-srp" module LeapWebUsers -- cgit v1.2.3 From bcc0f11caeef1b09712b9b62e1607237885d1af5 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 30 Oct 2012 14:42:04 +0100 Subject: using rails_warden bit of refactoring without rails_warden the failure app action was not getting set properly. --- users/app/controllers/sessions_controller.rb | 2 -- users/config/initializers/warden.rb | 35 +++++++++++++++++++++------- users/leap_web_users.gemspec | 2 +- users/lib/leap_web_users/engine.rb | 2 +- 4 files changed, 28 insertions(+), 13 deletions(-) (limited to 'users') diff --git a/users/app/controllers/sessions_controller.rb b/users/app/controllers/sessions_controller.rb index 3872866..7b7799c 100644 --- a/users/app/controllers/sessions_controller.rb +++ b/users/app/controllers/sessions_controller.rb @@ -6,12 +6,10 @@ class SessionsController < ApplicationController end def create - debugger env['warden'].authenticate! end def update - debugger env['warden'].authenticate! end diff --git a/users/config/initializers/warden.rb b/users/config/initializers/warden.rb index bb7dc13..98dd99c 100644 --- a/users/config/initializers/warden.rb +++ b/users/config/initializers/warden.rb @@ -1,6 +1,8 @@ -Rails.configuration.middleware.use Warden::Manager do |manager| - manager.default_strategies :secure_remote_password - manager.failure_app = SessionsController +Rails.configuration.middleware.use RailsWarden::Manager do |config| + config.default_strategies :secure_remote_password + config.failure_app = SessionsController + config.default_scope = :user + config.scope_defaults :user, :action => :new end # Setup Session Serialization @@ -18,31 +20,46 @@ end Warden::Strategies.add(:secure_remote_password) do def valid? - id && ( params['A'] || params['client_auth'] ) + handshake? || authentication? end def authenticate! - if params['client_auth'] && session[:handshake] + if authentication? validate! - else + else # handshake initialize! end end protected + def handshake? + params['A'] && params['login'] + end + + def authentication? + params['client_auth'] && session[:handshake] + end + def validate! srp_session = session.delete(:handshake) user = srp_session.authenticate(params['client_auth'].hex) - user.nil? ? fail!("Could not log in") : success!(u) + user.nil? ? fail!("Could not log in") : success!(user) end def initialize! user = User.find_by_param(id) session[:handshake] = user.initialize_auth(params['A'].hex) - custom! [200, {}, [session[:handshake].to_json]] + custom! json_response(session[:handshake]) rescue RECORD_NOT_FOUND - fail! "User not found" + fail! "User not found!" + end + + def json_response(object) + [ 200, + {"Content-Type" => "application/json; charset=utf-8"}, + [object.to_json] + ] end def id diff --git a/users/leap_web_users.gemspec b/users/leap_web_users.gemspec index 477265e..053f8dc 100644 --- a/users/leap_web_users.gemspec +++ b/users/leap_web_users.gemspec @@ -18,5 +18,5 @@ Gem::Specification.new do |s| s.add_dependency "leap_web_core", LeapWeb::VERSION s.add_dependency "ruby-srp", "~> 0.1.3" - s.add_dependency "warden" + s.add_dependency "rails_warden" end diff --git a/users/lib/leap_web_users/engine.rb b/users/lib/leap_web_users/engine.rb index 25c110e..42ca072 100644 --- a/users/lib/leap_web_users/engine.rb +++ b/users/lib/leap_web_users/engine.rb @@ -1,7 +1,7 @@ # thou shall require all your dependencies in an engine. require "leap_web_core" require "leap_web_core/ui_dependencies" -require "warden" +require "rails_warden" require "ruby-srp" module LeapWebUsers -- cgit v1.2.3 From f2825d10e6447ea766fee085841e2b92b0477976 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 30 Oct 2012 15:36:16 +0100 Subject: sending proper error messages from warden. still need to translate these --- users/app/assets/javascripts/srp | 2 +- users/app/controllers/sessions_controller.rb | 7 +++++-- users/config/initializers/warden.rb | 8 ++++---- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'users') diff --git a/users/app/assets/javascripts/srp b/users/app/assets/javascripts/srp index 23350b5..3bf101b 160000 --- a/users/app/assets/javascripts/srp +++ b/users/app/assets/javascripts/srp @@ -1 +1 @@ -Subproject commit 23350b54ec2723e1b2e333626567c9fe9d1e2644 +Subproject commit 3bf101bc1ef3b5a58fe2f1e2a2e7a681f6de6c09 diff --git a/users/app/controllers/sessions_controller.rb b/users/app/controllers/sessions_controller.rb index 7b7799c..06d55eb 100644 --- a/users/app/controllers/sessions_controller.rb +++ b/users/app/controllers/sessions_controller.rb @@ -3,14 +3,17 @@ class SessionsController < ApplicationController skip_before_filter :verify_authenticity_token def new + if warden.winning_strategy + @errors = warden.winning_strategy.message + end end def create - env['warden'].authenticate! + authenticate! end def update - env['warden'].authenticate! + authenticate! end def destroy diff --git a/users/config/initializers/warden.rb b/users/config/initializers/warden.rb index 98dd99c..82753ec 100644 --- a/users/config/initializers/warden.rb +++ b/users/config/initializers/warden.rb @@ -1,10 +1,10 @@ Rails.configuration.middleware.use RailsWarden::Manager do |config| config.default_strategies :secure_remote_password config.failure_app = SessionsController - config.default_scope = :user - config.scope_defaults :user, :action => :new end +RailsWarden.unauthenticated_action = :new + # Setup Session Serialization class Warden::SessionSerializer def serialize(record) @@ -44,7 +44,7 @@ Warden::Strategies.add(:secure_remote_password) do def validate! srp_session = session.delete(:handshake) user = srp_session.authenticate(params['client_auth'].hex) - user.nil? ? fail!("Could not log in") : success!(user) + user ? success!(user) : fail!(:password => "Could not log in") end def initialize! @@ -52,7 +52,7 @@ Warden::Strategies.add(:secure_remote_password) do session[:handshake] = user.initialize_auth(params['A'].hex) custom! json_response(session[:handshake]) rescue RECORD_NOT_FOUND - fail! "User not found!" + fail! :login => "User not found!" end def json_response(object) -- cgit v1.2.3 From 5acc88d8a376b2e25e5230d8174667106754c786 Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 31 Oct 2012 10:40:03 +0100 Subject: user creation should send ok flag so js can start login --- users/app/models/user.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'users') diff --git a/users/app/models/user.rb b/users/app/models/user.rb index 1afb9db..737e083 100644 --- a/users/app/models/user.rb +++ b/users/app/models/user.rb @@ -44,7 +44,10 @@ class User < CouchRest::Model::Base end def to_json(options={}) - super(options.merge(:only => ['login', 'password_salt'])) + { + :login => login, + :ok => valid? + }.to_json(options) end def initialize_auth(aa) -- cgit v1.2.3 From b92d418ebec6486a9e728c57f38f82d4c3343341 Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 31 Oct 2012 10:40:51 +0100 Subject: using json template for rendering the warden failures --- users/app/views/sessions/new.json.erb | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 users/app/views/sessions/new.json.erb (limited to 'users') diff --git a/users/app/views/sessions/new.json.erb b/users/app/views/sessions/new.json.erb new file mode 100644 index 0000000..36154b8 --- /dev/null +++ b/users/app/views/sessions/new.json.erb @@ -0,0 +1,3 @@ +{ +"errors": <%= raw @errors.to_json %> +} -- cgit v1.2.3 From e1fc3f4850ee73e0591bd67a92b104db4f63e4cb Mon Sep 17 00:00:00 2001 From: Azul Date: Sun, 4 Nov 2012 21:01:27 +0100 Subject: stubbing current_user the warden way --- .../controller_extension/authentication.rb | 2 +- .../test/functional/application_controller_test.rb | 7 +++---- users/test/functional/helper_methods_test.rb | 15 ++++++--------- users/test/integration/api/account_flow_test.rb | 4 ++-- users/test/support/auth_test_helper.rb | 21 +++++++++++---------- 5 files changed, 23 insertions(+), 26 deletions(-) (limited to 'users') diff --git a/users/app/controllers/controller_extension/authentication.rb b/users/app/controllers/controller_extension/authentication.rb index 50cf0d1..0408b77 100644 --- a/users/app/controllers/controller_extension/authentication.rb +++ b/users/app/controllers/controller_extension/authentication.rb @@ -8,7 +8,7 @@ module ControllerExtension::Authentication end def current_user - @current_user ||= env['warden'].user + @current_user ||= request.env['warden'].user end def logged_in? diff --git a/users/test/functional/application_controller_test.rb b/users/test/functional/application_controller_test.rb index 69bcb2f..857bae5 100644 --- a/users/test/functional/application_controller_test.rb +++ b/users/test/functional/application_controller_test.rb @@ -8,20 +8,19 @@ class ApplicationControllerTest < ActionController::TestCase end def test_authorize_redirect - stub_logged_out @controller.send(:authorize) assert_access_denied end def test_authorized - @user = stub_logged_in + login @controller.send(:authorize) assert_access_denied(false) end def test_authorize_admin - @user = stub_logged_in - @user.expects(:is_admin?).returns(false) + login + @current_user.expects(:is_admin?).returns(false) @controller.send(:authorize_admin) assert_access_denied end diff --git a/users/test/functional/helper_methods_test.rb b/users/test/functional/helper_methods_test.rb index c0eaf61..2b2375c 100644 --- a/users/test/functional/helper_methods_test.rb +++ b/users/test/functional/helper_methods_test.rb @@ -16,26 +16,23 @@ class HelperMethodsTest < ActionController::TestCase @controller end - def test_current_user_with_caching - @user = stub_logged_in - assert_equal @user, current_user - assert_equal @user, current_user # tests caching + def test_current_user + login + assert_equal @current_user, current_user end def test_logged_in - @user = stub_logged_in + login assert logged_in? end def test_logged_out - stub_logged_out assert !logged_in? end def test_admin - bool = stub - @user = stub_logged_in - @user.expects(:is_admin?).returns(bool) + login + @current_user.expects(:is_admin?).returns(bool = stub) assert_equal bool, admin? end diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index 5800d46..69e0599 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -4,7 +4,7 @@ class AccountFlowTest < ActionDispatch::IntegrationTest # this test wraps the api and implements the interface the ruby-srp client. def handshake(login, aa) - post "sessions", :login => login, 'A' => aa.to_s(16) + post "sessions", :login => login, 'A' => aa.to_s(16), :format => :json assert_response :success response = JSON.parse(@response.body) if response['errors'] @@ -15,7 +15,7 @@ class AccountFlowTest < ActionDispatch::IntegrationTest end def validate(m) - put "sessions/" + @login, :client_auth => m.to_s(16) + put "sessions/" + @login, :client_auth => m.to_s(16), :format => :json assert_response :success return JSON.parse(@response.body) end diff --git a/users/test/support/auth_test_helper.rb b/users/test/support/auth_test_helper.rb index 9412058..f211597 100644 --- a/users/test/support/auth_test_helper.rb +++ b/users/test/support/auth_test_helper.rb @@ -1,17 +1,18 @@ module AuthTestHelper + extend ActiveSupport::Concern - def stub_logged_in - @user_id = stub - @user = stub - session[:user_id] = @user_id - User.expects(:find).once.with(@user_id).returns(@user) - return @user + # Controller will fetch current user from warden. + # Make it pick up our current_user + included do + setup do + request.env['warden'] ||= stub :user => nil + end end - def stub_logged_out - @user_id = stub - session[:user_id] = @user_id - User.expects(:find).once.with(@user_id).returns(nil) + def login(user = nil) + @current_user = user || stub + request.env['warden'] = stub :user => @current_user + return @current_user end def assert_access_denied(denied = true) -- cgit v1.2.3 From ef90c45998b33ba8606c3786875e21496ace4686 Mon Sep 17 00:00:00 2001 From: Azul Date: Sun, 4 Nov 2012 22:14:13 +0100 Subject: fixed functional tests --- .../controller_extension/authentication.rb | 4 +- users/app/controllers/sessions_controller.rb | 6 +- users/test/functional/sessions_controller_test.rb | 85 ++++++++++------------ users/test/integration/api/account_flow_test.rb | 7 +- 4 files changed, 49 insertions(+), 53 deletions(-) (limited to 'users') diff --git a/users/app/controllers/controller_extension/authentication.rb b/users/app/controllers/controller_extension/authentication.rb index 0408b77..87f7921 100644 --- a/users/app/controllers/controller_extension/authentication.rb +++ b/users/app/controllers/controller_extension/authentication.rb @@ -7,8 +7,8 @@ module ControllerExtension::Authentication helper_method :current_user, :logged_in?, :admin? end - def current_user - @current_user ||= request.env['warden'].user + def authentication_error + warden.winning_strategy.try(:message) end def logged_in? diff --git a/users/app/controllers/sessions_controller.rb b/users/app/controllers/sessions_controller.rb index 06d55eb..722265a 100644 --- a/users/app/controllers/sessions_controller.rb +++ b/users/app/controllers/sessions_controller.rb @@ -3,9 +3,7 @@ class SessionsController < ApplicationController skip_before_filter :verify_authenticity_token def new - if warden.winning_strategy - @errors = warden.winning_strategy.message - end + @errors = authentication_error end def create @@ -17,7 +15,7 @@ class SessionsController < ApplicationController end def destroy - session[:user_id] = nil + logout redirect_to root_path end end diff --git a/users/test/functional/sessions_controller_test.rb b/users/test/functional/sessions_controller_test.rb index 47d7052..4bad12f 100644 --- a/users/test/functional/sessions_controller_test.rb +++ b/users/test/functional/sessions_controller_test.rb @@ -2,74 +2,67 @@ require 'test_helper' class SessionsControllerTest < ActionController::TestCase - def setup + setup do @user = stub :login => "me", :id => 123 @client_hex = 'a123' - @client_rnd = @client_hex.hex - @server_hex = 'b123' - @server_rnd = @server_hex.hex - @server_rnd_exp = 'e123'.hex - @salt = 'stub user salt' - @server_handshake = stub :aa => @client_rnd, :bb => @server_rnd, :b => @server_rnd_exp - @server_auth = 'adfe' end test "should get login screen" do + request.env['warden'].expects(:winning_strategy) get :new assert_response :success + assert_equal "text/html", response.content_type + assert_template "sessions/new" end - test "should perform handshake" do - @user.expects(:initialize_auth). - with(@client_rnd). - returns(@server_handshake) - @server_handshake.expects(:to_json). - returns({'B' => @server_hex, 'salt' => @salt}.to_json) - User.expects(:find_by_param).with(@user.login).returns(@user) - post :create, :login => @user.login, 'A' => @client_hex - assert_equal @server_handshake, session[:handshake] + test "renders json" do + request.env['warden'].expects(:winning_strategy) + get :new, :format => :json assert_response :success - assert_json_response :B => @server_hex, :salt => @salt + assert_json_response :errors => nil end - test "should report user not found" do - unknown = "login_that_does_not_exist" - User.expects(:find_by_param).with(unknown).raises(RECORD_NOT_FOUND) - post :create, :login => unknown + test "renders warden errors" do + strategy = stub :message => "Warden auth did not work" + request.env['warden'].expects(:winning_strategy).returns(strategy) + get :new, :format => :json assert_response :success - assert_json_response :errors => {"login" => ["unknown user"]} + assert_json_response :errors => strategy.message end - test "should authorize" do - session[:handshake] = @server_handshake - @server_handshake.expects(:authenticate!). - with(@client_rnd). - returns(@user) - @server_handshake.expects(:to_json). - returns({:M2 => @server_auth}.to_json) - post :update, :id => @user.login, :client_auth => @client_hex - assert_nil session[:handshake] - assert_json_response :M2 => @server_auth - assert_equal @user.id, session[:user_id] + test "should perform handshake" do + assert_raises ActionView::MissingTemplate do + request.env['warden'].expects(:authenticate!) + post :create, :login => @user.login, 'A' => @client_hex + assert params['A'] + assert params['login'] + end end - test "should report wrong password" do - session[:handshake] = @server_handshake - @server_handshake.expects(:authenticate!). - with(@client_rnd). - raises(WRONG_PASSWORD) - post :update, :id => @user.login, :client_auth => @client_hex - assert_nil session[:handshake] - assert_nil session[:user_id] - assert_json_response :errors => {"password" => ["wrong password"]} + test "should authorize" do + assert_raises ActionView::MissingTemplate do + request.env['warden'].expects(:authenticate!) + session[:handshake] = stub + post :update, :id => @user.login, :client_auth => @client_hex + assert params['client_auth'] + assert session[:handshake] + end end - test "logout should reset sessions user_id" do - session[:user_id] = "set" + test "logout should reset warden user" do + expect_warden_logout delete :destroy - assert_nil session[:user_id] assert_response :redirect assert_redirected_to root_url end + def expect_warden_logout + raw = mock('raw session') do + expects(:inspect) + end + request.env['warden'].expects(:raw_session).returns(raw) + request.env['warden'].expects(:logout) + end + + end diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index 69e0599..dc475b5 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -1,6 +1,11 @@ require 'test_helper' class AccountFlowTest < ActionDispatch::IntegrationTest + include Warden::Test::Helpers + + def teardown + Warden.test_reset! + end # this test wraps the api and implements the interface the ruby-srp client. def handshake(login, aa) @@ -52,7 +57,7 @@ class AccountFlowTest < ActionDispatch::IntegrationTest test "signup and wrong password login attempt" do srp = SRP::Client.new(@login, "wrong password") server_auth = srp.authenticate(self) - assert_equal ["wrong password"], server_auth["errors"]['password'] + assert_equal "Could not log in", server_auth["errors"]['password'] assert_nil server_auth["M2"] end -- cgit v1.2.3 From da2804c8f8a800851fa1863f579e2b8e9a57b4cc Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 6 Nov 2012 11:51:10 +0100 Subject: first steps towards warden srp testing --- users/app/controllers/sessions_controller.rb | 1 + users/test/integration/api/account_flow_test.rb | 26 ++++++--- .../warden_strategy_secure_remote_password_test.rb | 61 ++++++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 users/test/unit/warden_strategy_secure_remote_password_test.rb (limited to 'users') diff --git a/users/app/controllers/sessions_controller.rb b/users/app/controllers/sessions_controller.rb index 722265a..72e2892 100644 --- a/users/app/controllers/sessions_controller.rb +++ b/users/app/controllers/sessions_controller.rb @@ -11,6 +11,7 @@ class SessionsController < ApplicationController end def update + debugger authenticate! end diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index dc475b5..4dcca24 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -1,7 +1,16 @@ require 'test_helper' -class AccountFlowTest < ActionDispatch::IntegrationTest +CONFIG_RU = (Rails.root + 'config.ru').to_s +OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first + +class AccountFlowTest < ActiveSupport::TestCase + include Rack::Test::Methods include Warden::Test::Helpers + include LeapWebCore::AssertResponses + + def app + OUTER_APP + end def teardown Warden.test_reset! @@ -9,9 +18,9 @@ class AccountFlowTest < ActionDispatch::IntegrationTest # this test wraps the api and implements the interface the ruby-srp client. def handshake(login, aa) - post "sessions", :login => login, 'A' => aa.to_s(16), :format => :json - assert_response :success - response = JSON.parse(@response.body) + post "/sessions.json", :login => login, 'A' => aa.to_s(16), :format => :json + assert last_response.successful? + response = JSON.parse(last_response.body) if response['errors'] raise RECORD_NOT_FOUND.new(response['errors']) else @@ -20,9 +29,10 @@ class AccountFlowTest < ActionDispatch::IntegrationTest end def validate(m) - put "sessions/" + @login, :client_auth => m.to_s(16), :format => :json - assert_response :success - return JSON.parse(@response.body) + debugger + put "/sessions/" + @login + '.json', :client_auth => m.to_s(16), :format => :json + assert last_response.successful? + return JSON.parse(last_response.body) end def setup @@ -45,7 +55,7 @@ class AccountFlowTest < ActionDispatch::IntegrationTest test "signup response" do assert_json_response :login => @login, :ok => true - assert_response :success + assert last_response.successful? end test "signup and login with srp via api" do diff --git a/users/test/unit/warden_strategy_secure_remote_password_test.rb b/users/test/unit/warden_strategy_secure_remote_password_test.rb new file mode 100644 index 0000000..ee68fe7 --- /dev/null +++ b/users/test/unit/warden_strategy_secure_remote_password_test.rb @@ -0,0 +1,61 @@ +class WardenStrategySecureRemotePasswordTest < ActiveSupport::TestCase + + setup do + @user = stub :login => "me", :id => 123 + @client_hex = 'a123' + @client_rnd = @client_hex.hex + @server_hex = 'b123' + @server_rnd = @server_hex.hex + @server_rnd_exp = 'e123'.hex + @salt = 'stub user salt' + @server_handshake = stub :aa => @client_rnd, :bb => @server_rnd, :b => @server_rnd_exp + @server_auth = 'adfe' + end + + + test "should perform handshake" do + @user.expects(:initialize_auth). + with(@client_rnd). + returns(@server_handshake) + @server_handshake.expects(:to_json). + returns({'B' => @server_hex, 'salt' => @salt}.to_json) + User.expects(:find_by_param).with(@user.login).returns(@user) + assert_equal @server_handshake, session[:handshake] + assert_response :success + assert_json_response :B => @server_hex, :salt => @salt + end + + test "should report user not found" do + unknown = "login_that_does_not_exist" + User.expects(:find_by_param).with(unknown).raises(RECORD_NOT_FOUND) + post :create, :login => unknown + assert_response :success + assert_json_response :errors => {"login" => ["unknown user"]} + end + + test "should authorize" do + session[:handshake] = @server_handshake + @server_handshake.expects(:authenticate!). + with(@client_rnd). + returns(@user) + @server_handshake.expects(:to_json). + returns({:M2 => @server_auth}.to_json) + post :update, :id => @user.login, :client_auth => @client_hex + assert_nil session[:handshake] + assert_json_response :M2 => @server_auth + assert_equal @user.id, session[:user_id] + end + + test "should report wrong password" do + session[:handshake] = @server_handshake + @server_handshake.expects(:authenticate!). + with(@client_rnd). + raises(WRONG_PASSWORD) + post :update, :id => @user.login, :client_auth => @client_hex + assert_nil session[:handshake] + assert_nil session[:user_id] + assert_json_response :errors => {"password" => ["wrong password"]} + end + + +end -- cgit v1.2.3 From 63c5b2cafdefbd9b13297faa57ee2f18a5c07bf5 Mon Sep 17 00:00:00 2001 From: Azul Date: Fri, 9 Nov 2012 16:05:22 +0100 Subject: got integration test and login flow to work --- users/app/controllers/sessions_controller.rb | 2 +- users/config/initializers/warden.rb | 5 ++--- users/test/integration/api/account_flow_test.rb | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'users') diff --git a/users/app/controllers/sessions_controller.rb b/users/app/controllers/sessions_controller.rb index 72e2892..486f67e 100644 --- a/users/app/controllers/sessions_controller.rb +++ b/users/app/controllers/sessions_controller.rb @@ -11,8 +11,8 @@ class SessionsController < ApplicationController end def update - debugger authenticate! + render :json => session.delete(:handshake) end def destroy diff --git a/users/config/initializers/warden.rb b/users/config/initializers/warden.rb index 82753ec..11b950f 100644 --- a/users/config/initializers/warden.rb +++ b/users/config/initializers/warden.rb @@ -13,7 +13,7 @@ class Warden::SessionSerializer def deserialize(keys) klass, id = keys - klass.find(id) + klass.constantize.find(id) end end @@ -42,8 +42,7 @@ Warden::Strategies.add(:secure_remote_password) do end def validate! - srp_session = session.delete(:handshake) - user = srp_session.authenticate(params['client_auth'].hex) + user = session[:handshake].authenticate(params['client_auth'].hex) user ? success!(user) : fail!(:password => "Could not log in") end diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index 4dcca24..c9a7109 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -29,7 +29,6 @@ class AccountFlowTest < ActiveSupport::TestCase end def validate(m) - debugger put "/sessions/" + @login + '.json', :client_auth => m.to_s(16), :format => :json assert last_response.successful? return JSON.parse(last_response.body) -- cgit v1.2.3 From 5b300b554682c232c0955bdb0dd3d8263dde901e Mon Sep 17 00:00:00 2001 From: Azul Date: Fri, 9 Nov 2012 16:45:54 +0100 Subject: seperated the warden classes from the initializer also commented the sessions controller test a bit and fixed it --- users/config/initializers/warden.rb | 61 ---------------------- users/lib/leap_web_users/engine.rb | 3 ++ users/lib/warden/session_serializer.rb | 13 +++++ .../warden/strategies/secure_remote_password.rb | 57 ++++++++++++++++++++ users/test/functional/sessions_controller_test.rb | 29 +++++----- 5 files changed, 89 insertions(+), 74 deletions(-) create mode 100644 users/lib/warden/session_serializer.rb create mode 100644 users/lib/warden/strategies/secure_remote_password.rb (limited to 'users') diff --git a/users/config/initializers/warden.rb b/users/config/initializers/warden.rb index 11b950f..45feb6c 100644 --- a/users/config/initializers/warden.rb +++ b/users/config/initializers/warden.rb @@ -5,64 +5,3 @@ end RailsWarden.unauthenticated_action = :new -# Setup Session Serialization -class Warden::SessionSerializer - def serialize(record) - [record.class.name, record.id] - end - - def deserialize(keys) - klass, id = keys - klass.constantize.find(id) - end -end - -Warden::Strategies.add(:secure_remote_password) do - - def valid? - handshake? || authentication? - end - - def authenticate! - if authentication? - validate! - else # handshake - initialize! - end - end - - protected - - def handshake? - params['A'] && params['login'] - end - - def authentication? - params['client_auth'] && session[:handshake] - end - - def validate! - user = session[:handshake].authenticate(params['client_auth'].hex) - user ? success!(user) : fail!(:password => "Could not log in") - end - - def initialize! - user = User.find_by_param(id) - session[:handshake] = user.initialize_auth(params['A'].hex) - custom! json_response(session[:handshake]) - rescue RECORD_NOT_FOUND - fail! :login => "User not found!" - end - - def json_response(object) - [ 200, - {"Content-Type" => "application/json; charset=utf-8"}, - [object.to_json] - ] - end - - def id - params["id"] || params["login"] - end -end - diff --git a/users/lib/leap_web_users/engine.rb b/users/lib/leap_web_users/engine.rb index 42ca072..7033576 100644 --- a/users/lib/leap_web_users/engine.rb +++ b/users/lib/leap_web_users/engine.rb @@ -4,6 +4,9 @@ require "leap_web_core/ui_dependencies" require "rails_warden" require "ruby-srp" +require "warden/session_serializer" +require "warden/strategies/secure_remote_password" + module LeapWebUsers class Engine < ::Rails::Engine diff --git a/users/lib/warden/session_serializer.rb b/users/lib/warden/session_serializer.rb new file mode 100644 index 0000000..81d7076 --- /dev/null +++ b/users/lib/warden/session_serializer.rb @@ -0,0 +1,13 @@ +module Warden + # Setup Session Serialization + class SessionSerializer + def serialize(record) + [record.class.name, record.id] + end + + def deserialize(keys) + klass, id = keys + klass.constantize.find(id) + end + end +end diff --git a/users/lib/warden/strategies/secure_remote_password.rb b/users/lib/warden/strategies/secure_remote_password.rb new file mode 100644 index 0000000..8266e2d --- /dev/null +++ b/users/lib/warden/strategies/secure_remote_password.rb @@ -0,0 +1,57 @@ +module Warden + module Strategies + class SecureRemotePassword < Warden::Strategies::Base + + def valid? + handshake? || authentication? + end + + def authenticate! + if authentication? + validate! + else # handshake + initialize! + end + end + + protected + + def handshake? + params['A'] && params['login'] + end + + def authentication? + params['client_auth'] && session[:handshake] + end + + def validate! + user = session[:handshake].authenticate(params['client_auth'].hex) + user ? success!(user) : fail!(:password => "Could not log in") + end + + def initialize! + user = User.find_by_param(id) + session[:handshake] = user.initialize_auth(params['A'].hex) + custom! json_response(session[:handshake]) + rescue RECORD_NOT_FOUND + fail! :login => "User not found!" + end + + def json_response(object) + [ 200, + {"Content-Type" => "application/json; charset=utf-8"}, + [object.to_json] + ] + end + + def id + params["id"] || params["login"] + end + end + end + Warden::Strategies.add :secure_remote_password, + Warden::Strategies::SecureRemotePassword + +end + + diff --git a/users/test/functional/sessions_controller_test.rb b/users/test/functional/sessions_controller_test.rb index 4bad12f..8f2d95c 100644 --- a/users/test/functional/sessions_controller_test.rb +++ b/users/test/functional/sessions_controller_test.rb @@ -1,5 +1,8 @@ require 'test_helper' +# This is a simple controller unit test. +# We're stubbing out both warden and srp. +# There's an integration test testing the full rack stack and srp class SessionsControllerTest < ActionController::TestCase setup do @@ -30,23 +33,23 @@ class SessionsControllerTest < ActionController::TestCase assert_json_response :errors => strategy.message end + # Warden takes care of parsing the params and + # rendering the response. So not much to test here. test "should perform handshake" do - assert_raises ActionView::MissingTemplate do - request.env['warden'].expects(:authenticate!) - post :create, :login => @user.login, 'A' => @client_hex - assert params['A'] - assert params['login'] - end + request.env['warden'].expects(:authenticate!) + # make sure we don't get a template missing error: + @controller.stubs(:render) + post :create, :login => @user.login, 'A' => @client_hex end test "should authorize" do - assert_raises ActionView::MissingTemplate do - request.env['warden'].expects(:authenticate!) - session[:handshake] = stub - post :update, :id => @user.login, :client_auth => @client_hex - assert params['client_auth'] - assert session[:handshake] - end + request.env['warden'].expects(:authenticate!) + handshake = stub(:to_json => "JSON") + session[:handshake] = handshake + post :update, :id => @user.login, :client_auth => @client_hex + assert_nil session[:handshake] + assert_response :success + assert_equal handshake.to_json, @response.body end test "logout should reset warden user" do -- cgit v1.2.3 From 8bb19e57c5d7a40d7319c70b191d4e3145a172ce Mon Sep 17 00:00:00 2001 From: Azul Date: Mon, 12 Nov 2012 19:19:49 +0100 Subject: commented out an unfinished test --- users/test/unit/warden_strategy_secure_remote_password_test.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'users') diff --git a/users/test/unit/warden_strategy_secure_remote_password_test.rb b/users/test/unit/warden_strategy_secure_remote_password_test.rb index ee68fe7..79480f0 100644 --- a/users/test/unit/warden_strategy_secure_remote_password_test.rb +++ b/users/test/unit/warden_strategy_secure_remote_password_test.rb @@ -1,5 +1,7 @@ class WardenStrategySecureRemotePasswordTest < ActiveSupport::TestCase +# TODO : turn this into sth. real +=begin setup do @user = stub :login => "me", :id => 123 @client_hex = 'a123' @@ -57,5 +59,5 @@ class WardenStrategySecureRemotePasswordTest < ActiveSupport::TestCase assert_json_response :errors => {"password" => ["wrong password"]} end - +=end end -- cgit v1.2.3