Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package rubygem-omniauth-google-oauth2 for openSUSE:Factory checked in at 2021-01-21 21:56:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-omniauth-google-oauth2 (Old) and /work/SRC/openSUSE:Factory/.rubygem-omniauth-google-oauth2.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-omniauth-google-oauth2" Thu Jan 21 21:56:30 2021 rev:8 rq:865240 version:0.8.1 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-omniauth-google-oauth2/rubygem-omniauth-google-oauth2.changes 2020-03-07 21:39:20.756317013 +0100 +++ /work/SRC/openSUSE:Factory/.rubygem-omniauth-google-oauth2.new.28504/rubygem-omniauth-google-oauth2.changes 2021-01-21 21:56:33.221840411 +0100 @@ -1,0 +2,21 @@ +Wed Jan 20 13:02:21 UTC 2021 - Stephan Kulow <co...@suse.com> + +updated to version 0.8.1 + see installed CHANGELOG.md + + ## 0.8.1 - 2020-12-12 + + ### Added + - Support reading the access token from a json request body. + + ### Deprecated + - Nothing. + + ### Removed + - No longer verify the iat claim for JWT. + + ### Fixed + - A few minor issues with .rubocop.yml. + + +------------------------------------------------------------------- Old: ---- omniauth-google-oauth2-0.8.0.gem New: ---- omniauth-google-oauth2-0.8.1.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-omniauth-google-oauth2.spec ++++++ --- /var/tmp/diff_new_pack.UX3lKG/_old 2021-01-21 21:56:33.825840617 +0100 +++ /var/tmp/diff_new_pack.UX3lKG/_new 2021-01-21 21:56:33.829840618 +0100 @@ -1,7 +1,7 @@ # # spec file for package rubygem-omniauth-google-oauth2 # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -24,7 +24,7 @@ # Name: rubygem-omniauth-google-oauth2 -Version: 0.8.0 +Version: 0.8.1 Release: 0 %define mod_name omniauth-google-oauth2 %define mod_full_name %{mod_name}-%{version} ++++++ omniauth-google-oauth2-0.8.0.gem -> omniauth-google-oauth2-0.8.1.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.rubocop.yml new/.rubocop.yml --- old/.rubocop.yml 2019-08-22 08:40:10.000000000 +0200 +++ new/.rubocop.yml 2020-12-13 06:46:05.000000000 +0100 @@ -1,11 +1,9 @@ -ClassLength: - Enabled: false -Layout/IndentHeredoc: +Metrics/ClassLength: Enabled: false Metrics/AbcSize: Enabled: false Metrics/BlockLength: - ExcludedMethods: ['describe', 'context'] + ExcludedMethods: ['describe', 'context', 'shared_examples'] Metrics/CyclomaticComplexity: Enabled: false Metrics/LineLength: @@ -20,4 +18,3 @@ Enabled: false Gemspec/RequiredRubyVersion: Enabled: false - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.travis.yml new/.travis.yml --- old/.travis.yml 2019-08-22 08:40:10.000000000 +0200 +++ new/.travis.yml 2020-12-13 06:46:05.000000000 +0100 @@ -1,6 +1,5 @@ language: ruby rvm: - - '2.2.7' - '2.3.4' - '2.4.1' - '2.5.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md --- old/CHANGELOG.md 2019-08-22 08:40:10.000000000 +0200 +++ new/CHANGELOG.md 2020-12-13 06:46:05.000000000 +0100 @@ -1,6 +1,20 @@ # Changelog All notable changes to this project will be documented in this file. +## 0.8.1 - 2020-12-12 + +### Added +- Support reading the access token from a json request body. + +### Deprecated +- Nothing. + +### Removed +- No longer verify the iat claim for JWT. + +### Fixed +- A few minor issues with .rubocop.yml. + ## 0.8.0 - 2019-08-21 ### Added diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.md new/README.md --- old/README.md 2019-08-22 08:40:10.000000000 +0200 +++ new/README.md 2020-12-13 06:46:05.000000000 +0100 @@ -81,7 +81,9 @@ * `include_granted_scopes`: If this is provided with the value true, and the authorization request is granted, the authorization will include any previous authorizations granted to this user/application combination for other scopes. See Google's [Incremental Authorization](https://developers.google.com/accounts/docs/OAuth2WebServer#incrementalAuth) for additional details. -* `openid_realm`: Set the OpenID realm value, to allow upgrading from OpenID based authentication to OAuth 2 based authentication. When this is set correctly an `openid_id` value will be set in `[:extra][:id_info]` in the authentication hash with the value of the user's OpenID ID URL. +* `openid_realm`: Set the OpenID realm value, to allow upgrading from OpenID based authentication to OAuth 2 based authentication. When this is set correctly an `openid_id` value will be set in `['extra']['id_info']` in the authentication hash with the value of the user's OpenID ID URL. + +* `provider_ignores_state`: You will need to set this to `true` when using the `One-time Code Flow` below. In this flow there is no server side redirect that would set the state. Here's an example of a possible configuration where the strategy name is changed, the user is asked for extra permissions, the user is always prompted to select their account when logging in and the user's profile picture is returned as a thumbnail: @@ -176,6 +178,8 @@ Then make sure your callbacks controller is setup. ```ruby +# app/controllers/users/omniauth_callbacks_controller.rb: + class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def google_oauth2 # You need to implement the method below in your model (e.g. app/models/user.rb) @@ -185,7 +189,7 @@ flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google' sign_in_and_redirect @user, event: :authentication else - session['devise.google_data'] = request.env['omniauth.auth'].except(:extra) # Removing extra as it can overflow some session stores + session['devise.google_data'] = request.env['omniauth.auth'].except('extra') # Removing extra as it can overflow some session stores redirect_to new_user_registration_url, alert: @user.errors.full_messages.join("\n") end end @@ -223,7 +227,7 @@ ### One-time Code Flow (Hybrid Authentication) -Google describes the One-time Code Flow [here](https://developers.google.com/+/web/signin/server-side-flow). This hybrid authentication flow has significant functional and security advantages over a pure server-side or pure client-side flow. The following steps occur in this flow: +Google describes the One-time Code Flow [here](https://developers.google.com/identity/sign-in/web/server-side-flow). This hybrid authentication flow has significant functional and security advantages over a pure server-side or pure client-side flow. The following steps occur in this flow: 1. The client (web browser) authenticates the user directly via Google's JS API. During this process assorted modals may be rendered by Google. 2. On successful authentication, Google returns a one-time use code, which requires the Google client secret (which is only available server-side). @@ -232,7 +236,7 @@ This flow is immune to replay attacks, and conveys no useful information to a man in the middle. -The omniauth-google-oauth2 gem supports this mode of operation out of the box. Implementors simply need to add the appropriate JavaScript to their web page, and they can take advantage of this flow. An example JavaScript snippet follows. +The omniauth-google-oauth2 gem supports this mode of operation when `provider_ignores_state` is set to `true`. Implementors simply need to add the appropriate JavaScript to their web page, and they can take advantage of this flow. An example JavaScript snippet follows. ```javascript // Basic hybrid auth example following the pattern at: @@ -247,7 +251,7 @@ // Ready. $('.google-login-button').click(function(e) { e.preventDefault(); - + gapi.auth2.authorize({ client_id: 'YOUR_CLIENT_ID', cookie_policy: 'single_host_origin', @@ -260,7 +264,7 @@ success: function(data) { // response from server } - }); + }); } else { // google authentication failed } @@ -280,6 +284,66 @@ If you're making POST requests to `/auth/google_oauth2/callback` from another domain, then you need to make sure `'X-Requested-With': 'XMLHttpRequest'` header is included with your request, otherwise your server might respond with `OAuth2::Error, : Invalid Value` error. +#### Getting around the `redirect_uri_mismatch` error (See [Issue #365](https://github.com/zquestz/omniauth-google-oauth2/issues/365)) + +If you are struggling with a persistent `redirect_uri_mismatch`, you can instead pass the `access_token` from [`getAuthResponse`](https://developers.google.com/identity/sign-in/web/reference#googleusergetauthresponseincludeauthorizationdata) directly to the `auth/google_oauth2/callback` endpoint, like so: + +```javascript +// Initialize the GoogleAuth object +let googleAuth; +gapi.load('client:auth2', async () => { + await gapi.client.init({ scope: '...', client_id: '...' }); + googleAuth = gapi.auth2.getAuthInstance(); +}); + +// Call this when the Google Sign In button is clicked +async function signInGoogle() { + const googleUser = await googleAuth.signIn(); // wait for the user to authorize through the modal + const { access_token } = googleUser.getAuthResponse(); + + const data = new FormData(); + data.append('access_token', access_token); + + const response = await api.post('/auth/google_oauth2/callback', data) + console.log(response); +} +``` + +#### Using Axios +If you're making a GET resquests from another domain using `access_token`. +``` +axios + .get( + 'url(path to your callback}', + { params: { access_token: 'token' } }, + headers.... + ) +``` + +If you're making a POST resquests from another domain using `access_token`. +``` +axios + .post( + 'url(path to your callback}', + { access_token: 'token' }, + headers.... + ) + +--OR-- + +axios + .post( + 'url(path to your callback}', + null, + { + params: { + access_token: 'token' + }, + headers.... + } + ) +``` + ## Fixing Protocol Mismatch for `redirect_uri` in Rails Just set the `full_host` in OmniAuth based on the Rails.env. Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/examples/Gemfile new/examples/Gemfile --- old/examples/Gemfile 2019-08-22 08:40:10.000000000 +0200 +++ new/examples/Gemfile 2020-12-13 06:46:05.000000000 +0100 @@ -2,6 +2,6 @@ source 'https://rubygems.org' -gem 'omniauth-google-oauth2', '~> 0.8.0' +gem 'omniauth-google-oauth2', '~> 0.8.1' gem 'rubocop' gem 'sinatra', '~> 1.4' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/examples/omni_auth.rb new/examples/omni_auth.rb --- old/examples/omni_auth.rb 2019-08-22 08:40:10.000000000 +0200 +++ new/examples/omni_auth.rb 2020-12-13 06:46:05.000000000 +0100 @@ -10,6 +10,10 @@ # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'email,profile' + # Custom redirect_uri + # + # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'email,profile', redirect_uri: 'https://localhost:3000/redirect' + # Manual setup for offline access with a refresh token. # # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'offline' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/omniauth/google_oauth2/version.rb new/lib/omniauth/google_oauth2/version.rb --- old/lib/omniauth/google_oauth2/version.rb 2019-08-22 08:40:10.000000000 +0200 +++ new/lib/omniauth/google_oauth2/version.rb 2020-12-13 06:46:05.000000000 +0100 @@ -2,6 +2,6 @@ module OmniAuth module GoogleOauth2 - VERSION = '0.8.0' + VERSION = '0.8.1' end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/omniauth/strategies/google_oauth2.rb new/lib/omniauth/strategies/google_oauth2.rb --- old/lib/omniauth/strategies/google_oauth2.rb 2019-08-22 08:40:10.000000000 +0200 +++ new/lib/omniauth/strategies/google_oauth2.rb 2020-12-13 06:46:05.000000000 +0100 @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'jwt' +require 'oauth2' require 'omniauth/strategies/oauth2' require 'uri' @@ -13,6 +14,7 @@ BASE_SCOPES = %w[profile email openid].freeze DEFAULT_SCOPE = 'email,profile' USER_INFO_URL = 'https://www.googleapis.com/oauth2/v3/userinfo' + IMAGE_SIZE_REGEXP = /(s\d+(-c)?)|(w\d+-h\d+(-c)?)|(w\d+(-c)?)|(h\d+(-c)?)|c/ option :name, 'google_oauth2' option :skip_friends, true @@ -74,7 +76,7 @@ verify_sub: false, verify_expiration: true, verify_not_before: true, - verify_iat: true, + verify_iat: false, verify_jti: false, leeway: options[:jwt_leeway]) @@ -106,18 +108,24 @@ def get_access_token(request) verifier = request.params['code'] redirect_uri = request.params['redirect_uri'] + access_token = request.params['access_token'] if verifier && request.xhr? client_get_token(verifier, redirect_uri || 'postmessage') elsif verifier client_get_token(verifier, redirect_uri || callback_url) - elsif verify_token(request.params['access_token']) + elsif access_token && verify_token(access_token) ::OAuth2::AccessToken.from_hash(client, request.params.dup) elsif request.content_type =~ /json/i begin body = JSON.parse(request.body.read) request.body.rewind # rewind request body for downstream middlewares verifier = body && body['code'] - client_get_token(verifier, 'postmessage') if verifier + access_token = body && body['access_token'] + if verifier + client_get_token(verifier, 'postmessage') + elsif verify_token(access_token) + ::OAuth2::AccessToken.from_hash(client, body.dup) + end rescue JSON::ParserError => e warn "[omniauth google-oauth2] JSON parse error=#{e}" end @@ -164,6 +172,10 @@ if path_index && image_size_opts_passed? u.path.insert(path_index, image_params) u.path = u.path.gsub('//', '/') + + # Check if the image is already sized! + split_path = u.path.split('/') + u.path = u.path.sub("/#{split_path[-3]}", '') if split_path[-3] =~ IMAGE_SIZE_REGEXP end u.query = strip_unnecessary_query_parameters(u.query) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2019-08-22 08:40:10.000000000 +0200 +++ new/metadata 2020-12-13 06:46:05.000000000 +0100 @@ -1,15 +1,15 @@ --- !ruby/object:Gem::Specification name: omniauth-google-oauth2 version: !ruby/object:Gem::Version - version: 0.8.0 + version: 0.8.1 platform: ruby authors: - Josh Ellithorpe - Yury Korolev -autorequire: +autorequire: bindir: bin cert_chain: [] -date: 2019-08-22 00:00:00.000000000 Z +date: 2020-12-13 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: jwt @@ -26,6 +26,20 @@ - !ruby/object:Gem::Version version: '2.0' - !ruby/object:Gem::Dependency + name: oauth2 + requirement: !ruby/object:Gem::Requirement + requirements: + - - "~>" + - !ruby/object:Gem::Version + version: '1.1' + type: :runtime + prerelease: false + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - "~>" + - !ruby/object:Gem::Version + version: '1.1' +- !ruby/object:Gem::Dependency name: omniauth requirement: !ruby/object:Gem::Requirement requirements: @@ -125,7 +139,7 @@ licenses: - MIT metadata: {} -post_install_message: +post_install_message: rdoc_options: [] require_paths: - lib @@ -140,9 +154,9 @@ - !ruby/object:Gem::Version version: '0' requirements: [] -rubyforge_project: +rubyforge_project: rubygems_version: 2.7.9 -signing_key: +signing_key: specification_version: 4 summary: A Google OAuth2 strategy for OmniAuth 1.x test_files: [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/omniauth-google-oauth2.gemspec new/omniauth-google-oauth2.gemspec --- old/omniauth-google-oauth2.gemspec 2019-08-22 08:40:10.000000000 +0200 +++ new/omniauth-google-oauth2.gemspec 2020-12-13 06:46:05.000000000 +0100 @@ -21,6 +21,7 @@ gem.required_ruby_version = '>= 2.2' gem.add_runtime_dependency 'jwt', '>= 2.0' + gem.add_runtime_dependency 'oauth2', '~> 1.1' gem.add_runtime_dependency 'omniauth', '>= 1.1.1' gem.add_runtime_dependency 'omniauth-oauth2', '>= 1.6' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/omniauth/strategies/google_oauth2_spec.rb new/spec/omniauth/strategies/google_oauth2_spec.rb --- old/spec/omniauth/strategies/google_oauth2_spec.rb 2019-08-22 08:40:10.000000000 +0200 +++ new/spec/omniauth/strategies/google_oauth2_spec.rb 2020-12-13 06:46:05.000000000 +0100 @@ -349,7 +349,7 @@ before { allow(subject).to receive(:access_token).and_return(access_token) } describe 'id_token' do - shared_examples 'id_token issued by valid issuer' do |issuer| # rubocop:disable Metrics/BlockLength + shared_examples 'id_token issued by valid issuer' do |issuer| context 'when the id_token is passed into the access token' do let(:token_info) do { @@ -462,6 +462,12 @@ expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg') end + it 'should return the image with size specified in the `image_size` option when sizing is in the picture' do + @options = { image_size: 50 } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh4.googleusercontent.com/url/s96-c/photo.jpg' } } + expect(subject.info[:image]).to eq('https://lh4.googleusercontent.com/url/s50/photo.jpg') + end + it 'should handle a picture with too many slashes correctly' do @options = { image_size: 50 } allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url//photo.jpg' } } @@ -492,24 +498,48 @@ expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40/photo.jpg') end + it 'should return the image with width and height specified in the `image_size` option when sizing is in the picture' do + @options = { image_size: { width: 50, height: 40 } } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/w100-h80-c/photo.jpg' } } + expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40/photo.jpg') + end + it 'should return square image when `image_aspect_ratio` is specified' do @options = { image_aspect_ratio: 'square' } allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } } expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/c/photo.jpg') end + it 'should return square image when `image_aspect_ratio` is specified and sizing is in the picture' do + @options = { image_aspect_ratio: 'square' } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/c/photo.jpg' } } + expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/c/photo.jpg') + end + it 'should return square sized image when `image_aspect_ratio` and `image_size` is set' do @options = { image_aspect_ratio: 'square', image_size: 50 } allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } } expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50-c/photo.jpg') end + it 'should return square sized image when `image_aspect_ratio` and `image_size` is set and sizing is in the picture' do + @options = { image_aspect_ratio: 'square', image_size: 50 } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/s90/photo.jpg' } } + expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50-c/photo.jpg') + end + it 'should return square sized image when `image_aspect_ratio` and `image_size` has height and width' do @options = { image_aspect_ratio: 'square', image_size: { width: 50, height: 40 } } allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } } expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40-c/photo.jpg') end + it 'should return square sized image when `image_aspect_ratio` and `image_size` has height and width and sizing is in the picture' do + @options = { image_aspect_ratio: 'square', image_size: { width: 50, height: 40 } } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/w100-h80/photo.jpg' } } + expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40-c/photo.jpg') + end + it 'should return original image if image url does not end in `photo.jpg`' do @options = { image_size: 50 } allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photograph.jpg' } } @@ -599,6 +629,22 @@ subject.build_access_token end + it 'reads the access token from a json request body' do + body = StringIO.new(%({"access_token":"valid_access_token"})) + + allow(request).to receive(:xhr?).and_return(false) + allow(request).to receive(:content_type).and_return('application/json') + allow(request).to receive(:body).and_return(body) + expect(subject).to receive(:client).and_return(:client) + + expect(subject).to receive(:verify_token).with('valid_access_token').and_return true + + token = subject.build_access_token + expect(token).to be_instance_of(::OAuth2::AccessToken) + expect(token.token).to eq('valid_access_token') + expect(token.client).to eq(:client) + end + it 'should use callback_url without query_string if this is not an AJAX request' do allow(request).to receive(:xhr?).and_return(false) allow(request).to receive(:params).and_return('code' => 'valid_code')