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 <[email protected]>
+
+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')