require 'spec_helper' require 'multi_json' require 'jwt' describe OmniAuth::Strategies::GoogleIdToken do # rubocop:disable Metrics/BlockLength let(:rsa_private) { OpenSSL::PKey::RSA.generate 512 } let(:rsa_public) { rsa_private.public_key } let(:response_json) { MultiJson.load(last_response.body) } let(:id_token) { 'tokensss' } let(:payload) do { 'iss' => 'https://accounts.google.com', 'nbf' => 161_803_398_874, 'aud' => 'http://example.com', 'sub' => '3141592653589793238', 'hd' => 'gmail.com', 'email' => 'bob@example.com', 'email_verified' => true, 'azp' => '314159265-pi.apps.googleusercontent.com', 'name' => 'Elisa Beckett', 'picture' => 'https://lh3.googleusercontent.com/a-/e2718281828459045235360uler', 'given_name' => 'Elisa', 'family_name' => 'Beckett', 'iat' => 1_596_474_000, 'exp' => 1_596_477_600, 'jti' => 'abc161803398874def' } end let(:aud_claim) { payload[:aud] } let(:azp_claim) { payload[:azp] } let(:client_id) { 'test_client_id' } let(:args) do [ { aud_claim: payload[:aud], azp_claim: payload[:azp], client_id: client_id } ] end let(:app) do the_args = args Rack::Builder.new do |b| b.use Rack::Session::Cookie, secret: 'sekrit' b.use OmniAuth::Strategies::GoogleIdToken, *the_args b.run ->(env) { [200, {}, [(env['omniauth.auth'] || {}).to_json]] } end end let(:api_url) { '/auth/google_id_token' } describe 'Subclassing Behavior' do subject { fresh_strategy } it 'performs the OmniAuth::Strategy included hook' do expect(OmniAuth.strategies).to include(OmniAuth::Strategies::GoogleIdToken) end end describe 'request phase' do it 'should redirect to the configured login url' do post api_url expect(last_response.status).to eq(302) expect(last_response.headers['Location'].gsub(/&state=[0-9a-z]*/, '')).to eq('https://accounts.google.com/o/oauth2/auth?scope=profile%20email%20openid&access_type=offline&include_granted_scopes=true&redirect_uri=http%3A%2F%2Fexample.org%2Fauth%2Fgoogle_id_token%2Fcallback&response_type=token%20id_token&client_id=test_client_id') # Removed state random field end end context 'callback phase' do it 'should decode the response' do allow(::Google::Auth::IDTokens::Verifier).to receive(:verify_oidc) .with(id_token, aud: aud_claim, azp: azp_claim) .and_return(payload) post "#{api_url}/callback", id_token: id_token expect(response_json['info']['email']).to eq('bob@example.com') end it 'should not work without required fields' do payload.delete('email') allow(::Google::Auth::IDTokens::Verifier).to receive(:verify_oidc) .with(id_token, aud: aud_claim, azp: azp_claim) .and_return(payload) post "#{api_url}/callback", id_token: id_token expect(last_response.status).to eq(302) end it 'should assign the uid' do allow(::Google::Auth::IDTokens::Verifier).to receive(:verify_oidc) .with(id_token, aud: aud_claim, azp: azp_claim) .and_return(payload) post "#{api_url}/callback", id_token: id_token expect(response_json['uid']).to eq('3141592653589793238') end end end