BigW Consortium Gitlab

sessions_controller_spec.rb 8.04 KB
Newer Older
1 2 3 4 5 6 7 8
require 'spec_helper'

describe SessionsController do
  describe '#create' do
    before do
      @request.env['devise.mapping'] = Devise.mappings[:user]
    end

9
    context 'when using standard authentications' do
10 11 12 13 14
      context 'invalid password' do
        it 'does not authenticate user' do
          post(:create, user: { login: 'invalid', password: 'invalid' })

          expect(response)
Connor Shea committed
15
            .to set_flash.now[:alert].to /Invalid Login or password/
16 17 18
        end
      end

19 20 21
      context 'when using valid password', :redis do
        include UserActivitiesHelpers

22 23 24 25 26 27 28
        let(:user) { create(:user) }

        it 'authenticates user correctly' do
          post(:create, user: { login: user.username, password: user.password })

          expect(subject.current_user). to eq user
        end
29

30
        it 'creates an audit log record' do
31
          expect { post(:create, user: { login: user.username, password: user.password }) }.to change { SecurityEvent.count }.by(1)
32 33 34
          expect(SecurityEvent.last.details[:with]).to eq('standard')
        end

35 36
        include_examples 'user login request with unique ip limit', 302 do
          def request
37 38
            post(:create, user: { login: user.username, password: user.password })
            expect(subject.current_user).to eq user
39
            subject.sign_out user
40
          end
41
        end
42 43 44 45

        it 'updates the user activity' do
          expect do
            post(:create, user: { login: user.username, password: user.password })
46
          end.to change { user_activity(user) }
47
        end
48 49 50
      end
    end

51
    context 'when using two-factor authentication via OTP' do
52 53 54 55 56 57
      let(:user) { create(:user, :two_factor) }

      def authenticate_2fa(user_params)
        post(:create, { user: user_params }, { otp_user_id: user.id })
      end

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
      context 'remember_me field' do
        it 'sets a remember_user_token cookie when enabled' do
          allow(controller).to receive(:find_user).and_return(user)
          expect(controller).
            to receive(:remember_me).with(user).and_call_original

          authenticate_2fa(remember_me: '1', otp_attempt: user.current_otp)

          expect(response.cookies['remember_user_token']).to be_present
        end

        it 'does nothing when disabled' do
          allow(controller).to receive(:find_user).and_return(user)
          expect(controller).not_to receive(:remember_me)

          authenticate_2fa(remember_me: '0', otp_attempt: user.current_otp)

          expect(response.cookies['remember_user_token']).to be_nil
        end
      end

79 80 81
      ##
      # See #14900 issue
      #
82 83 84
      context 'when authenticating with login and OTP of another user' do
        context 'when another user has 2FA enabled' do
          let(:another_user) { create(:user, :two_factor) }
85

86 87 88 89
          context 'when OTP is valid for another user' do
            it 'does not authenticate' do
              authenticate_2fa(login: another_user.username,
                               otp_attempt: another_user.current_otp)
90

91
              expect(subject.current_user).not_to eq another_user
92
            end
93 94
          end

95 96 97 98
          context 'when OTP is invalid for another user' do
            it 'does not authenticate' do
              authenticate_2fa(login: another_user.username,
                               otp_attempt: 'invalid')
99

100
              expect(subject.current_user).not_to eq another_user
101
            end
102 103
          end

104 105 106 107 108 109 110 111
          context 'when authenticating with OTP' do
            context 'when OTP is valid' do
              it 'authenticates correctly' do
                authenticate_2fa(otp_attempt: user.current_otp)

                expect(subject.current_user).to eq user
              end
            end
112

113
            context 'when OTP is invalid' do
114
              before { authenticate_2fa(otp_attempt: 'invalid') }
115

116
              it 'does not authenticate' do
117
                expect(subject.current_user).not_to eq user
118 119 120
              end

              it 'warns about invalid OTP code' do
121 122
                expect(response).to set_flash.now[:alert]
                  .to /Invalid two-factor code/
123
              end
124 125 126
            end
          end

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
          context 'when the user is on their last attempt' do
            before do
              user.update(failed_attempts: User.maximum_attempts.pred)
            end

            context 'when OTP is valid' do
              it 'authenticates correctly' do
                authenticate_2fa(otp_attempt: user.current_otp)

                expect(subject.current_user).to eq user
              end
            end

            context 'when OTP is invalid' do
              before { authenticate_2fa(otp_attempt: 'invalid') }

              it 'does not authenticate' do
                expect(subject.current_user).not_to eq user
              end

              it 'warns about invalid login' do
                expect(response).to set_flash.now[:alert]
                  .to /Invalid Login or password/
              end

              it 'locks the user' do
                expect(user.reload).to be_access_locked
              end

              it 'keeps the user locked on future login attempts' do
                post(:create, user: { login: user.username, password: user.password })

                expect(response)
                  .to set_flash.now[:alert].to /Invalid Login or password/
              end
            end
          end

165 166
          context 'when another user does not have 2FA enabled' do
            let(:another_user) { create(:user) }
167

168 169 170
            it 'does not leak that 2FA is disabled for another user' do
              authenticate_2fa(login: another_user.username,
                               otp_attempt: 'invalid')
171

172 173
              expect(response).to set_flash.now[:alert]
                .to /Invalid two-factor code/
174 175 176 177
            end
          end
        end
      end
178 179 180 181 182 183 184 185 186 187 188 189 190 191

      it "creates an audit log record" do
        expect { authenticate_2fa(login: user.username, otp_attempt: user.current_otp) }.to change { SecurityEvent.count }.by(1)
        expect(SecurityEvent.last.details[:with]).to eq("two-factor")
      end
    end

    context 'when using two-factor authentication via U2F device' do
      let(:user) { create(:user, :two_factor) }

      def authenticate_2fa_u2f(user_params)
        post(:create, { user: user_params }, { otp_user_id: user.id })
      end

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
      context 'remember_me field' do
        it 'sets a remember_user_token cookie when enabled' do
          allow(U2fRegistration).to receive(:authenticate).and_return(true)
          allow(controller).to receive(:find_user).and_return(user)
          expect(controller).
            to receive(:remember_me).with(user).and_call_original

          authenticate_2fa_u2f(remember_me: '1', login: user.username, device_response: "{}")

          expect(response.cookies['remember_user_token']).to be_present
        end

        it 'does nothing when disabled' do
          allow(U2fRegistration).to receive(:authenticate).and_return(true)
          allow(controller).to receive(:find_user).and_return(user)
          expect(controller).not_to receive(:remember_me)

          authenticate_2fa_u2f(remember_me: '0', login: user.username, device_response: "{}")

          expect(response.cookies['remember_user_token']).to be_nil
        end
      end

215 216 217 218 219
      it "creates an audit log record" do
        allow(U2fRegistration).to receive(:authenticate).and_return(true)
        expect { authenticate_2fa_u2f(login: user.username, device_response: "{}") }.to change { SecurityEvent.count }.by(1)
        expect(SecurityEvent.last.details[:with]).to eq("two-factor-via-u2f-device")
      end
220 221
    end
  end
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237

  describe '#new' do
    before do
      @request.env['devise.mapping'] = Devise.mappings[:user]
    end

    it 'redirects correctly for referer on same host with params' do
      search_path = '/search?search=seed_project'
      allow(controller.request).to receive(:referer).
        and_return('http://%{host}%{path}' % { host: Gitlab.config.gitlab.host, path: search_path })

      get(:new, redirect_to_referer: :yes)

      expect(controller.stored_location_for(:redirect)).to eq(search_path)
    end
  end
238
end