From 02ffbcf0d89eeba05f5433abb56fe4c9820a03c7 Mon Sep 17 00:00:00 2001 From: Andrey Novikov Date: Mon, 28 Feb 2022 21:21:55 +0300 Subject: [PATCH] Output granted scopes in credentials block of the auth hash --- lib/omniauth/strategies/google_oauth2.rb | 20 ++++++++++++++++--- .../omniauth/strategies/google_oauth2_spec.rb | 17 +++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/omniauth/strategies/google_oauth2.rb b/lib/omniauth/strategies/google_oauth2.rb index d6cb636..4ce32eb 100644 --- a/lib/omniauth/strategies/google_oauth2.rb +++ b/lib/omniauth/strategies/google_oauth2.rb @@ -60,6 +60,11 @@ def authorize_params ) end + credentials do + # Tokens and expiration will be used from OAuth2 strategy credentials block + prune!({ 'scope' => token_info(access_token.token)['scope'] }) + end + extra do hash = {} hash[:id_token] = access_token['id_token'] @@ -215,12 +220,21 @@ def strip_unnecessary_query_parameters(query_parameters) URI.encode_www_form(stripped_params) end + def token_info(access_token) + return nil unless access_token + + @token_info ||= Hash.new do |h, k| + h[k] = client.request(:get, 'https://www.googleapis.com/oauth2/v3/tokeninfo', params: { access_token: access_token }).parsed + end + + @token_info[access_token] + end + def verify_token(access_token) return false unless access_token - raw_response = client.request(:get, 'https://www.googleapis.com/oauth2/v3/tokeninfo', - params: { access_token: access_token }).parsed - raw_response['aud'] == options.client_id || options.authorized_client_ids.include?(raw_response['aud']) + token_info = token_info(access_token) + token_info['aud'] == options.client_id || options.authorized_client_ids.include?(token_info['aud']) end def verify_hd(access_token) diff --git a/spec/omniauth/strategies/google_oauth2_spec.rb b/spec/omniauth/strategies/google_oauth2_spec.rb index 1e365fa..3a2bcf0 100644 --- a/spec/omniauth/strategies/google_oauth2_spec.rb +++ b/spec/omniauth/strategies/google_oauth2_spec.rb @@ -350,13 +350,28 @@ describe '#credentials' do let(:client) { OAuth2::Client.new('abc', 'def') } let(:access_token) { OAuth2::AccessToken.from_hash(client, access_token: 'valid_access_token', expires_at: 123_456_789, refresh_token: 'valid_refresh_token') } - before(:each) { allow(subject).to receive(:access_token).and_return(access_token) } + before(:each) do + allow(subject).to receive(:access_token).and_return(access_token) + subject.options.client_options[:connection_build] = proc do |builder| + builder.request :url_encoded + builder.adapter :test do |stub| + stub.get('/oauth2/v3/tokeninfo?access_token=valid_access_token') do + [200, { 'Content-Type' => 'application/json; charset=UTF-8' }, JSON.dump( + aud: '000000000000.apps.googleusercontent.com', + sub: '123456789', + scope: 'profile email' + )] + end + end + end + end it 'should return access token and (optionally) refresh token' do expect(subject.credentials.to_h).to \ match(hash_including( 'token' => 'valid_access_token', 'refresh_token' => 'valid_refresh_token', + 'scope' => 'profile email', 'expires_at' => 123_456_789, 'expires' => true ))