diff --git a/enterprise/app/controllers/enterprise/devise_overrides/sessions_controller.rb b/enterprise/app/controllers/enterprise/devise_overrides/sessions_controller.rb index 17e3ad682..b5a6a2ac2 100644 --- a/enterprise/app/controllers/enterprise/devise_overrides/sessions_controller.rb +++ b/enterprise/app/controllers/enterprise/devise_overrides/sessions_controller.rb @@ -1,12 +1,14 @@ module Enterprise::DeviseOverrides::SessionsController def create - check_saml_user + if saml_user_attempting_password_login? + render json: { + success: false, + errors: [I18n.t('messages.login_saml_user')] + }, status: :unauthorized + return + end + super - rescue CustomExceptions::Base => e - render json: { - success: false, - errors: [e.message] - }, status: e.http_status_code end def render_create_success @@ -35,14 +37,14 @@ module Enterprise::DeviseOverrides::SessionsController private - def check_saml_user - return if params[:email].blank? + def saml_user_attempting_password_login? + return false if params[:email].blank? user = User.from_email(params[:email]) - return unless user&.provider == 'saml' + return false unless user&.provider == 'saml' - return if params[:sso_auth_token].present? && user.valid_sso_auth_token?(params[:sso_auth_token]) + return false if params[:sso_auth_token].present? && user.valid_sso_auth_token?(params[:sso_auth_token]) - raise CustomExceptions::Base.new(I18n.t('messages.login_saml_user'), :unauthorized) + true end end diff --git a/spec/enterprise/controllers/enterprise/devise_overrides/session_controller_spec.rb b/spec/enterprise/controllers/enterprise/devise_overrides/session_controller_spec.rb index 89f8794ee..8e04af776 100644 --- a/spec/enterprise/controllers/enterprise/devise_overrides/session_controller_spec.rb +++ b/spec/enterprise/controllers/enterprise/devise_overrides/session_controller_spec.rb @@ -5,32 +5,70 @@ RSpec.describe 'Enterprise Audit API', type: :request do let!(:user) { create(:user, password: 'Password1!', account: account) } describe 'POST /sign_in' do - it 'creates a sign_in audit event wwith valid credentials' do - params = { email: user.email, password: 'Password1!' } + context 'with SAML user attempting password login' do + let!(:saml_settings) { create(:account_saml_settings, account: account) } + let!(:saml_user) { create(:user, email: 'saml@example.com', provider: 'saml', account: account) } - expect do - post new_user_session_url, - params: params, - as: :json - end.to change(Enterprise::AuditLog, :count).by(1) + it 'prevents login and returns SAML authentication error' do + params = { email: saml_user.email, password: 'Password1!' } - expect(response).to have_http_status(:success) - expect(response.body).to include(user.email) + post new_user_session_url, params: params, as: :json - # Check if the sign_in event is created - user.reload - expect(user.audits.last.action).to eq('sign_in') - expect(user.audits.last.associated_id).to eq(account.id) - expect(user.audits.last.associated_type).to eq('Account') + expect(response).to have_http_status(:unauthorized) + json_response = JSON.parse(response.body) + expect(json_response['success']).to eq(false) + expect(json_response['errors']).to include(I18n.t('messages.login_saml_user')) + end + + it 'allows login with valid SSO token' do + valid_token = saml_user.generate_sso_auth_token + params = { email: saml_user.email, sso_auth_token: valid_token, password: 'Password1!' } + + expect do + post new_user_session_url, params: params, as: :json + end.to change(Enterprise::AuditLog, :count).by(1) + + expect(response).to have_http_status(:success) + expect(response.body).to include(saml_user.email) + end end - it 'will not create a sign_in audit event with invalid credentials' do - params = { email: user.email, password: 'invalid' } - expect do - post new_user_session_url, - params: params, - as: :json - end.not_to change(Enterprise::AuditLog, :count) + context 'with regular user credentials' do + it 'creates a sign_in audit event wwith valid credentials' do + params = { email: user.email, password: 'Password1!' } + + expect do + post new_user_session_url, + params: params, + as: :json + end.to change(Enterprise::AuditLog, :count).by(1) + + expect(response).to have_http_status(:success) + expect(response.body).to include(user.email) + + # Check if the sign_in event is created + user.reload + expect(user.audits.last.action).to eq('sign_in') + expect(user.audits.last.associated_id).to eq(account.id) + expect(user.audits.last.associated_type).to eq('Account') + end + + it 'will not create a sign_in audit event with invalid credentials' do + params = { email: user.email, password: 'invalid' } + expect do + post new_user_session_url, + params: params, + as: :json + end.not_to change(Enterprise::AuditLog, :count) + end + end + + context 'with blank email' do + it 'skips SAML check and processes normally' do + params = { email: '', password: 'Password1!' } + post new_user_session_url, params: params, as: :json + expect(response).to have_http_status(:unauthorized) + end end end