omniauth_callbacks_controller_spec.rb 6.0 KB
Newer Older
1 2
require 'spec_helper'

3
describe OmniauthCallbacksController, type: :controller do
4 5
  include LoginHelpers

6 7
  describe 'omniauth' do
    let(:user) { create(:omniauth_user, extern_uid: extern_uid, provider: provider) }
8

T
Tiago Botelho 已提交
9
    before do
10 11
      mock_auth_hash(provider.to_s, extern_uid, user.email)
      stub_omniauth_provider(provider, context: request)
12
    end
13

14 15
    context 'when the user is on the last sign in attempt' do
      let(:extern_uid) { 'my-uid' }
16

17 18 19
      before do
        user.update(failed_attempts: User.maximum_attempts.pred)
        subject.response = ActionDispatch::Response.new
20
      end
21

22 23
      context 'when using a form based provider' do
        let(:provider) { :ldap }
24

25 26 27
        it 'locks the user when sign in fails' do
          allow(subject).to receive(:params).and_return(ActionController::Parameters.new(username: user.username))
          request.env['omniauth.error.strategy'] = OmniAuth::Strategies::LDAP.new(nil)
28

29
          subject.send(:failure)
T
Tiago Botelho 已提交
30

31 32
          expect(user.reload).to be_access_locked
        end
33
      end
34

35 36
      context 'when using a button based provider' do
        let(:provider) { :github }
37

38 39
        it 'does not lock the user when sign in fails' do
          request.env['omniauth.error.strategy'] = OmniAuth::Strategies::GitHub.new(nil)
40

41
          subject.send(:failure)
42

43
          expect(user.reload).not_to be_access_locked
T
Tiago Botelho 已提交
44
        end
45
      end
46
    end
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
    context 'when a redirect fragment is provided' do
      let(:provider) { :jwt }
      let(:extern_uid) { 'my-uid' }

      before do
        request.env['omniauth.params'] = { 'redirect_fragment' => 'L101' }
      end

      context 'when a redirect url is stored' do
        it 'redirects with fragment' do
          post provider, nil, { user_return_to: '/fake/url' }

          expect(response).to redirect_to('/fake/url#L101')
        end
      end

      context 'when a redirect url with a fragment is stored' do
        it 'redirects with the new fragment' do
          post provider, nil, { user_return_to: '/fake/url#replaceme' }

          expect(response).to redirect_to('/fake/url#L101')
        end
      end

      context 'when no redirect url is stored' do
        it 'does not redirect with the fragment' do
          post provider

          expect(response.redirect?).to be true
          expect(response.location).not_to include('#L101')
        end
      end
    end

82 83 84 85
    context 'strategies' do
      context 'github' do
        let(:extern_uid) { 'my-uid' }
        let(:provider) { :github }
T
Tiago Botelho 已提交
86

87
        it 'allows sign in' do
T
Tiago Botelho 已提交
88
          post provider
89

T
Tiago Botelho 已提交
90 91
          expect(request.env['warden']).to be_authenticated
        end
92

93 94
        shared_context 'sign_up' do
          let(:user) { double(email: 'new@example.com') }
95

96 97 98
          before do
            stub_omniauth_setting(block_auto_created_users: false)
          end
99
        end
T
Tiago Botelho 已提交
100

101 102
        context 'sign up' do
          include_context 'sign_up'
T
Tiago Botelho 已提交
103

104 105
          it 'is allowed' do
            post provider
T
Tiago Botelho 已提交
106

107 108
            expect(request.env['warden']).to be_authenticated
          end
T
Tiago Botelho 已提交
109 110
        end

111 112 113 114 115 116
        context 'when OAuth is disabled' do
          before do
            stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
            settings = Gitlab::CurrentSettings.current_application_settings
            settings.update(disabled_oauth_sign_in_sources: [provider.to_s])
          end
T
Tiago Botelho 已提交
117

118
          it 'prevents login via POST' do
T
Tiago Botelho 已提交
119 120 121 122
            post provider

            expect(request.env['warden']).not_to be_authenticated
          end
123 124 125 126 127 128 129 130 131

          it 'shows warning when attempting login' do
            post provider

            expect(response).to redirect_to new_user_session_path
            expect(flash[:alert]).to eq('Signing in using GitHub has been disabled')
          end

          it 'allows linking the disabled provider' do
132
            user.identities.destroy_all # rubocop: disable DestroyAll
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
            sign_in(user)

            expect { post provider }.to change { user.reload.identities.count }.by(1)
          end

          context 'sign up' do
            include_context 'sign_up'

            it 'is prevented' do
              post provider

              expect(request.env['warden']).not_to be_authenticated
            end
          end
        end
      end

      context 'auth0' do
        let(:extern_uid) { '' }
        let(:provider) { :auth0 }

        it 'does not allow sign in without extern_uid' do
          post 'auth0'

          expect(request.env['warden']).not_to be_authenticated
          expect(response.status).to eq(302)
          expect(controller).to set_flash[:alert].to('Wrong extern UID provided. Make sure Auth0 is configured correctly.')
T
Tiago Botelho 已提交
160
        end
161 162
      end
    end
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
  end

  describe '#saml' do
    let(:user) { create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: 'saml') }
    let(:mock_saml_response) { File.read('spec/fixtures/authentication/saml_response.xml') }
    let(:saml_config) { mock_saml_config_with_upstream_two_factor_authn_contexts }

    before do
      stub_omniauth_saml_config({ enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'],
                                  providers: [saml_config] })
      mock_auth_hash('saml', 'my-uid', user.email, mock_saml_response)
      request.env["devise.mapping"] = Devise.mappings[:user]
      request.env['omniauth.auth'] = Rails.application.env_config['omniauth.auth']
      post :saml, params: { SAMLResponse: mock_saml_response }
    end
178

179 180 181 182 183
    context 'when worth two factors' do
      let(:mock_saml_response) do
        File.read('spec/fixtures/authentication/saml_response.xml')
            .gsub('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN')
      end
184

185 186 187 188
      it 'expects user to be signed_in' do
        expect(request.env['warden']).to be_authenticated
      end
    end
189

190 191 192
    context 'when not worth two factors' do
      it 'expects user to provide second factor' do
        expect(response).to render_template('devise/sessions/two_factor')
T
Tiago Botelho 已提交
193 194
        expect(request.env['warden']).not_to be_authenticated
      end
195 196
    end
  end
197
end