openid_connect_spec.rb 3.72 KB
Newer Older
1 2 3
require 'spec_helper'

describe 'OpenID Connect requests' do
4
  let(:user) { create :user }
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
  let(:access_grant) { create :oauth_access_grant, application: application, resource_owner_id: user.id }
  let(:access_token) { create :oauth_access_token, application: application, resource_owner_id: user.id }

  def request_access_token
    login_as user

    post '/oauth/token',
      grant_type: 'authorization_code',
      code: access_grant.token,
      redirect_uri: application.redirect_uri,
      client_id: application.uid,
      client_secret: application.secret
  end

  def request_user_info
    get '/oauth/userinfo', nil, 'Authorization' => "Bearer #{access_token.token}"
  end

  def hashed_subject
    Digest::SHA256.hexdigest("#{user.id}-#{Rails.application.secrets.secret_key_base}")
  end

  context 'Application without OpenID scope' do
    let(:application) { create :oauth_application, scopes: 'api' }

    it 'token response does not include an ID token' do
      request_access_token

      expect(json_response).to include 'access_token'
      expect(json_response).not_to include 'id_token'
    end

    it 'userinfo response is unauthorized' do
      request_user_info

      expect(response).to have_http_status 403
      expect(response.body).to be_blank
    end
  end

  context 'Application with OpenID scope' do
    let(:application) { create :oauth_application, scopes: 'openid' }

    it 'token response includes an ID token' do
      request_access_token

      expect(json_response).to include 'id_token'
    end

    context 'UserInfo payload' do
      let(:user) do
        create(
          :user,
          name: 'Alice',
          username: 'alice',
          emails: [private_email, public_email],
          email: private_email.email,
          public_email: public_email.email,
          website_url: 'https://example.com',
64
          avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png")
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
        )
      end

      let(:public_email) { build :email, email: 'public@example.com' }
      let(:private_email) { build :email, email: 'private@example.com' }

      it 'includes all user information' do
        request_user_info

        expect(json_response).to eq({
          'sub'            => hashed_subject,
          'name'           => 'Alice',
          'nickname'       => 'alice',
          'email'          => 'public@example.com',
          'email_verified' => true,
          'website'        => 'https://example.com',
          'profile'        => 'http://localhost/alice',
82
          'picture'        => "http://localhost/uploads/user/avatar/#{user.id}/dk.png"
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
        })
      end
    end

    context 'ID token payload' do
      before do
        request_access_token
        @payload = JSON::JWT.decode(json_response['id_token'], :skip_verification)
      end

      it 'includes the Gitlab root URL' do
        expect(@payload['iss']).to eq Gitlab.config.gitlab.url
      end

      it 'includes the hashed user ID' do
        expect(@payload['sub']).to eq hashed_subject
      end

101
      it 'includes the time of the last authentication', :redis do
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
        expect(@payload['auth_time']).to eq user.current_sign_in_at.to_i
      end

      it 'does not include any unknown properties' do
        expect(@payload.keys).to eq %w[iss sub aud exp iat auth_time]
      end
    end

    context 'when user is blocked' do
      it 'returns authentication error' do
        access_grant
        user.block

        expect do
          request_access_token
        end.to throw_symbol :warden
      end
    end

    context 'when user is ldap_blocked' do
      it 'returns authentication error' do
        access_grant
        user.ldap_block

        expect do
          request_access_token
        end.to throw_symbol :warden
      end
    end
  end
end