From ed9005548bdff691562dd40518614851655fb58e Mon Sep 17 00:00:00 2001 From: Warsama Date: Fri, 6 Dec 2024 17:24:19 -0800 Subject: [PATCH 1/2] Added Rspec authentication tests --- spec/config/initializers/omniauth_spec.rb | 28 +++++++ spec/controllers/sessions_controller_spec.rb | 84 ++++++++++++++++++++ spec/models/user_spec.rb | 63 +++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 spec/config/initializers/omniauth_spec.rb create mode 100644 spec/controllers/sessions_controller_spec.rb create mode 100644 spec/models/user_spec.rb diff --git a/spec/config/initializers/omniauth_spec.rb b/spec/config/initializers/omniauth_spec.rb new file mode 100644 index 00000000..2da707b4 --- /dev/null +++ b/spec/config/initializers/omniauth_spec.rb @@ -0,0 +1,28 @@ +require 'rails_helper' + +RSpec.describe 'OmniAuth::Shibboleth Configuration' do + # set up mock shibboleth_config data + let(:shibboleth_config) do + { + host: 'medusatest.library.illinois.edu', + uid_field: 'eppn', + extra_fields: %w[eppn givenName mail org_dn sn telephoneNumber uid entitlement unscoped_affiliation], + request_type: 'header', + info_fields: { email: 'mail' } + } + end + + before do + # Mock Settings.shibboleth call and create the mocked object + allow(Settings).to receive(:shibboleth).and_return(OpenStruct.new(shibboleth_config)) + @strategy = OmniAuth::Strategies::Shibboleth.new(nil, shibboleth_config.symbolize_keys) + end + + it 'configures the Shibboleth provider with the correct settings' do + expect(@strategy.options[:host]).to eq('medusatest.library.illinois.edu') + expect(@strategy.options[:uid_field]).to eq('eppn') + expect(@strategy.options[:extra_fields]).to eq(%w[eppn givenName mail org_dn sn telephoneNumber uid entitlement unscoped_affiliation]) + expect(@strategy.options[:request_type]).to eq('header') + expect(@strategy.options[:info_fields]).to eq('email' => 'mail') + end +end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb new file mode 100644 index 00000000..aedb2f83 --- /dev/null +++ b/spec/controllers/sessions_controller_spec.rb @@ -0,0 +1,84 @@ +require 'rails_helper' + +RSpec.describe SessionsController, type: :controller do + describe 'GET #new' do + context 'in production environment' do + before { allow(Rails.env).to receive(:production?).and_return(true) } + + it 'saves the referring page in the session' do + request.env['HTTP_REFERER'] = '/login/page' + get :new + expect(session[:login_return_referer]).to eq('/login/page') + end + + it 'redirects to the Shibboleth login path' do + mocked_url = 'mock-shibboleth.local' + allow(MedusaCollectionRegistry::Application).to receive(:shibboleth_host).and_return(mocked_url) + get :new + expected_redirect_url = "/Shibboleth.sso/Login?target=https://#{mocked_url}/auth/shibboleth/callback" + expect(response).to redirect_to(expected_redirect_url) + end + end + + context 'in non-production environment' do + before { allow(Rails.env).to receive(:production?).and_return(false) } + + it 'redirects to /auth/identity' do + get :new + expect(response).to redirect_to('/auth/identity') + end + end + end + + describe 'POST #create' do + context 'in production environment' do + before do + allow(Rails.env).to receive(:production?).and_return(true) + request.env['omniauth.auth'] = { + provider: 'shibboleth', + uid: 'testuser@illinois.edu', + info: { + email: 'testuser@illinois.edu' + } + } + session[:login_return_uri] = '/dashboard' + end + + it 'authenticates the user and sets the session' do + post :create, params: { provider: 'shibboleth' } + user = User.find_by(uid: 'testuser@illinois.edu') + expect(user).to be_present + expect(session[:current_user_id]).to eq(user.id) + expect(response).to redirect_to('/dashboard') + end + + it 'redirects to login if Shibboleth attributes are missing' do + request.env['omniauth.auth'] = nil + post :create, params: { provider: 'shibboleth' } + expect(session[:current_user_id]).to be_nil + expect(response).to redirect_to(login_url) + end + end + + context 'in development environment' do + before do + allow(Rails.env).to receive(:production?).and_return(false) + end + + it 'authenticates the user in development mode' do + post :create, params: { provider: 'identity', auth_key: 'testuser@illinois.edu' } + user = User.find_by(uid: 'testuser@illinois.edu') + expect(user).to be_present + expect(session[:current_user_id]).to eq(user.id) + expect(response).to redirect_to(root_path) + end + + it 'redirects to login if auth_key is missing' do + request.params['auth_key'] = nil + post :create, params: { provider: 'identity' } + expect(session[:user_id]).to be_nil + expect(response).to redirect_to(login_url) + end + end + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb new file mode 100644 index 00000000..59a29722 --- /dev/null +++ b/spec/models/user_spec.rb @@ -0,0 +1,63 @@ +require 'rails_helper' + +RSpec.describe User, type: :model do + describe 'User creation' do + let(:user_attributes) do + { + uid: 'testuser@illinois.edu', + email: 'testuser@illinois.edu' + } + end + + context 'when creating a new user' do + it 'creates a user with the correct attributes' do + user = User.create!( + uid: user_attributes[:uid], + email: user_attributes[:email] + ) + + expect(user).to be_persisted + expect(user.uid).to eq('testuser@illinois.edu') + expect(user.email).to eq('testuser@illinois.edu') + end + end + + context 'when a user already exists with the same uid' do + it 'does not create a duplicate user' do + existing_user = User.create!( + uid: user_attributes[:uid], + email: user_attributes[:email] + ) + + expect { + User.create!( + uid: user_attributes[:uid], + email: user_attributes[:email] + ) + }.to raise_error(ActiveRecord::RecordInvalid, /Uid has already been taken/) + + expect(User.count).to eq(1) + expect(User.first).to eq(existing_user) + end + end + + context 'when a user already exists with the same email' do + it 'does not create a duplicate user' do + existing_user = User.create!( + uid: 'differentuid@illinois.edu', + email: user_attributes[:email] + ) + + expect { + User.create!( + uid: user_attributes[:uid], + email: user_attributes[:email] + ) + }.to raise_error(ActiveRecord::RecordInvalid, /Email has already been taken/) + + expect(User.count).to eq(1) + expect(User.first).to eq(existing_user) + end + end + end +end From 188f15db89d4b768e08ac56a319eeb689170b1de Mon Sep 17 00:00:00 2001 From: Warsama Date: Wed, 11 Dec 2024 15:21:17 -0800 Subject: [PATCH 2/2] Updated session controller tests with omniauth in test mode and mocks --- spec/controllers/sessions_controller_spec.rb | 26 ++++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index aedb2f83..f4decbe2 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -34,17 +34,22 @@ context 'in production environment' do before do allow(Rails.env).to receive(:production?).and_return(true) - request.env['omniauth.auth'] = { - provider: 'shibboleth', - uid: 'testuser@illinois.edu', - info: { - email: 'testuser@illinois.edu' - } - } + OmniAuth.config.test_mode = true session[:login_return_uri] = '/dashboard' end + after do + OmniAuth.config.test_mode = false + OmniAuth.config.mock_auth[:shibboleth] = nil + end + it 'authenticates the user and sets the session' do + OmniAuth.config.mock_auth[:shibboleth] = OmniAuth::AuthHash.new({ + provider: 'shibboleth', + uid: 'testuser@illinois.edu', + info: { email: 'testuser@illinois.edu' } + }) + request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:shibboleth] post :create, params: { provider: 'shibboleth' } user = User.find_by(uid: 'testuser@illinois.edu') expect(user).to be_present @@ -53,7 +58,12 @@ end it 'redirects to login if Shibboleth attributes are missing' do - request.env['omniauth.auth'] = nil + OmniAuth.config.mock_auth[:shibboleth] = OmniAuth::AuthHash.new({ + provider: 'shibboleth', + uid: nil, + info: { email: nil } + }) + request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:shibboleth] post :create, params: { provider: 'shibboleth' } expect(session[:current_user_id]).to be_nil expect(response).to redirect_to(login_url)