From 5ca23026b9bdeef12145b408f33d85acf1e1311a Mon Sep 17 00:00:00 2001 From: Josh Ellithorpe Date: Mon, 29 May 2017 23:15:19 -0700 Subject: [PATCH] Rubocop refactor and general cleanup --- .rubocop.yml | 18 ++ CHANGELOG.md | 9 +- Gemfile | 7 +- README.md | 128 ++++---- Rakefile | 5 +- examples/Gemfile | 6 +- examples/config.ru | 29 +- examples/omni_auth.rb | 28 +- lib/omniauth-google-oauth2.rb | 2 + lib/omniauth/google_oauth2.rb | 2 + lib/omniauth/google_oauth2/version.rb | 4 +- lib/omniauth/strategies/google_oauth2.rb | 108 +++---- omniauth-google-oauth2.gemspec | 28 +- .../omniauth/strategies/google_oauth2_spec.rb | 282 ++++++++++-------- spec/rubocop_spec.rb | 9 + spec/spec_helper.rb | 4 +- 16 files changed, 374 insertions(+), 295 deletions(-) create mode 100644 .rubocop.yml create mode 100644 spec/rubocop_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..b2bc16f --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,18 @@ +ClassLength: + Enabled: false +Layout/IndentHeredoc: + Enabled: false +Metrics/AbcSize: + Enabled: false +Metrics/BlockLength: + ExcludedMethods: ['describe', 'context'] +Metrics/CyclomaticComplexity: + Enabled: false +Metrics/LineLength: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/PerceivedComplexity: + Enabled: false +Style/FileName: + Enabled: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f3ec9b..0979b98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,22 @@ # Changelog All notable changes to this project will be documented in this file. -## 0.5.0 - 2017-02-13 +## 0.5.0 - 2017-05-29 ### Added -- Nothing. +- Rubocop checks to specs. +- Defaulted dev environment to ruby 2.3.4. ### Deprecated - Nothing. ### Removed - Testing support for older versions of ruby not supported by OmniAuth 1.5. +- Key `[:urls]['Google']` no longer exists, it has been renamed to `[:urls][:google]`. ### Fixed -- Nothing. +- Updated all code to rubocop conventions. This includes the Ruby 1.9 hash syntax when appropriate. +- Example javascript flow now picks up ENV vars for google key and secret. ## 0.4.1 - 2016-03-14 diff --git a/Gemfile b/Gemfile index bbb7613..7f4f5e9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,8 +1,5 @@ +# frozen_string_literal: true + source 'https://rubygems.org' gemspec - -group :example do - gem 'sinatra' - gem 'rack', '~> 1.6.0' -end diff --git a/README.md b/README.md index 69a1d91..37acbe7 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ For more details, read the Google docs: https://developers.google.com/accounts/d Add to your `Gemfile`: ```ruby -gem "omniauth-google-oauth2" +gem 'omniauth-google-oauth2' ``` Then `bundle install`. @@ -36,7 +36,7 @@ Here's an example for adding the middleware to a Rails app in `config/initialize ```ruby Rails.application.config.middleware.use OmniAuth::Builder do - provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"] + provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'] end ``` @@ -91,66 +91,69 @@ Here's an example of a possible configuration where the strategy name is changed ```ruby Rails.application.config.middleware.use OmniAuth::Builder do - provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"], + provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], { - :name => "google", - :scope => "email, profile, plus.me, http://gdata.youtube.com", - :prompt => "select_account", - :image_aspect_ratio => "square", - :image_size => 50 + name: 'google', + scope: 'email, profile, plus.me, http://gdata.youtube.com', + prompt: 'select_account', + image_aspect_ratio: 'square', + image_size: 50 } end ``` ## Auth Hash -Here's an example of an authentication hash available in the callback by accessing `request.env["omniauth.auth"]`: +Here's an example of an authentication hash available in the callback by accessing `request.env['omniauth.auth']`: ```ruby { - :provider => "google_oauth2", - :uid => "123456789", - :info => { - :name => "John Doe", - :email => "john@company_name.com", - :first_name => "John", - :last_name => "Doe", - :image => "https://lh3.googleusercontent.com/url/photo.jpg" - }, - :credentials => { - :token => "token", - :refresh_token => "another_token", - :expires_at => 1354920555, - :expires => true + "provider" => "google_oauth2", + "uid" => "100000000000000000000", + "info" => { + "name" => "John Smith", + "email" => "john@example.com", + "first_name" => "John", + "last_name" => "Smith", + "image" => "https://lh4.googleusercontent.com/photo.jpg", + "urls" => { + "google" => "https://plus.google.com/+JohnSmith" + } + }, + "credentials" => { + "token" => "TOKEN", + "refresh_token" => "REFRESH_TOKEN", + "expires_at" => 1496120719, + "expires" => true + }, + "extra" => { + "id_token" => "ID_TOKEN", + "id_info" => { + "azp" => "APP_ID", + "aud" => "APP_ID", + "sub" => "100000000000000000000", + "email" => "john@example.com", + "email_verified" => true, + "at_hash" => "HK6E_P6Dh8Y93mRNtsDB1Q", + "iss" => "accounts.google.com", + "iat" => 1496117119, + "exp" => 1496120719 }, - :extra => { - :raw_info => { - :sub => "123456789", - :email => "user@domain.example.com", - :email_verified => true, - :name => "John Doe", - :given_name => "John", - :family_name => "Doe", - :profile => "https://plus.google.com/123456789", - :picture => "https://lh3.googleusercontent.com/url/photo.jpg", - :gender => "male", - :birthday => "0000-06-25", - :locale => "en", - :hd => "company_name.com" - }, - :id_info => { - "iss" => "accounts.google.com", - "at_hash" => "HK6E_P6Dh8Y93mRNtsDB1Q", - "email_verified" => "true", - "sub" => "10769150350006150715113082367", - "azp" => "APP_ID", - "email" => "jsmith@example.com", - "aud" => "APP_ID", - "iat" => 1353601026, - "exp" => 1353604926, - "openid_id" => "https://www.google.com/accounts/o8/id?id=ABCdfdswawerSDFDsfdsfdfjdsf" - } + "raw_info" => { + "kind" => "plus#personOpenIdConnect", + "gender" => "male", + "sub" => "100000000000000000000", + "name" => "John Smith", + "given_name" => "John", + "family_name" => "Smith", + "profile" => "https://plus.google.com/+JohnSmith", + "picture" => "https://lh4.googleusercontent.com/photo.jpg?sz=50", + "email" => "john@example.com", + "email_verified" => "true", + "locale" => "en", + "hd" => "company.com" } + } } ``` @@ -161,19 +164,19 @@ First define your application id and secret in `config/initializers/devise.rb`. Configuration options can be passed as the last parameter here as key/value pairs. ```ruby -config.omniauth :google_oauth2, "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", { } +config.omniauth :google_oauth2, 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET', {} ``` Then add the following to 'config/routes.rb' so the callback routes are defined. ```ruby -devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } +devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' } ``` Make sure your model is omniauthable. Generally this is "/app/models/user.rb" ```ruby -devise :omniauthable, :omniauth_providers => [:google_oauth2] +devise :omniauthable, omniauth_providers: [:google_oauth2] ``` Then make sure your callbacks controller is setup. @@ -182,13 +185,13 @@ Then make sure your callbacks controller is setup. class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def google_oauth2 # You need to implement the method below in your model (e.g. app/models/user.rb) - @user = User.from_omniauth(request.env["omniauth.auth"]) + @user = User.from_omniauth(request.env['omniauth.auth']) if @user.persisted? - flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google" - sign_in_and_redirect @user, :event => :authentication + 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 @@ -200,12 +203,12 @@ and bind to or create the user ```ruby def self.from_omniauth(access_token) data = access_token.info - user = User.where(:email => data["email"]).first + user = User.where(email: data['email']).first # Uncomment the section below if you want users to be created if they don't exist # unless user - # user = User.create(name: data["name"], - # email: data["email"], + # user = User.create(name: data['name'], + # email: data['email'], # password: Devise.friendly_token[0,20] # ) # end @@ -269,8 +272,7 @@ window.gpAsyncInit = function() { }, function(response) { if (response && !response.error) { // google authentication succeed, now post data to server. - jQuery.ajax({type: 'POST', url: "/auth/google_oauth2/callback", -data: response, + jQuery.ajax({type: 'POST', url: '/auth/google_oauth2/callback', data: response, success: function(data) { // response from server } @@ -305,7 +307,7 @@ OmniAuth.config.full_host = Rails.env.production? ? 'https://domain.com' : 'http ## License -Copyright (c) 2016 by Josh Ellithorpe +Copyright (c) 2017 by Josh Ellithorpe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/Rakefile b/Rakefile index 591ff85..db36369 100644 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,8 @@ -#!/usr/bin/env rake +# frozen_string_literal: true + require File.join('bundler', 'gem_tasks') require File.join('rspec', 'core', 'rake_task') RSpec::Core::RakeTask.new(:spec) -task :default => :spec \ No newline at end of file +task default: :spec diff --git a/examples/Gemfile b/examples/Gemfile index 07708ae..5dcbf09 100644 --- a/examples/Gemfile +++ b/examples/Gemfile @@ -1,4 +1,6 @@ +# frozen_string_literal: true + source 'https://rubygems.org' -gem 'sinatra' -gem 'omniauth-google-oauth2' +gem 'omniauth-google-oauth2', '~> 0.5' +gem 'sinatra', '~> 1.4' diff --git a/examples/config.ru b/examples/config.ru index 1931f9e..a09d307 100644 --- a/examples/config.ru +++ b/examples/config.ru @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Sample app for Google OAuth2 Strategy # Make sure to setup the ENV variables GOOGLE_KEY and GOOGLE_SECRET # Run with "bundle exec rackup" @@ -15,6 +17,7 @@ require 'omniauth-google-oauth2' # http://railsapps.github.io/openssl-certificate-verify-failed.html OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE +# Main example app for omniauth-google-oauth2 class App < Sinatra::Base get '/' do <<-HTML @@ -37,7 +40,7 @@ class App < Sinatra::Base immediate: true, response_type: 'code', cookie_policy: 'single_host_origin', - client_id: 'YOUR_CLIENT_ID', + client_id: '#{ENV['GOOGLE_KEY']}', scope: 'email profile' }, function(response) { return; @@ -48,7 +51,7 @@ class App < Sinatra::Base immediate: false, response_type: 'code', cookie_policy: 'single_host_origin', - client_id: 'YOUR_CLIENT_ID', + client_id: '#{ENV['GOOGLE_KEY']}', scope: 'email profile' }, function(response) { if (response && !response.error) { @@ -80,26 +83,38 @@ class App < Sinatra::Base post '/auth/:provider/callback' do content_type 'text/plain' - request.env['omniauth.auth'].to_hash.inspect rescue "No Data" + begin + request.env['omniauth.auth'].to_hash.inspect + rescue + 'No Data' + end end get '/auth/:provider/callback' do content_type 'text/plain' - request.env['omniauth.auth'].to_hash.inspect rescue "No Data" + begin + request.env['omniauth.auth'].to_hash.inspect + rescue + 'No Data' + end end get '/auth/failure' do content_type 'text/plain' - request.env['omniauth.auth'].to_hash.inspect rescue "No Data" + begin + request.env['omniauth.auth'].to_hash.inspect + rescue + 'No Data' + end end end -use Rack::Session::Cookie, :secret => ENV['RACK_COOKIE_SECRET'] +use Rack::Session::Cookie, secret: ENV['RACK_COOKIE_SECRET'] use OmniAuth::Builder do # For additional provider examples please look at 'omni_auth.rb' # The key provider_ignores_state is only for AJAX flows. It is not recommended for normal logins. - provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], {access_type: "offline", prompt: "consent", provider_ignores_state: true, scope: 'email,profile,calendar'} + provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'offline', prompt: 'consent', provider_ignores_state: true, scope: 'email,profile,calendar' end run App.new diff --git a/examples/omni_auth.rb b/examples/omni_auth.rb index be65fa9..127b62a 100644 --- a/examples/omni_auth.rb +++ b/examples/omni_auth.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Google's OAuth2 docs. Make sure you are familiar with all the options # before attempting to configure this gem. # https://developers.google.com/accounts/docs/OAuth2Login @@ -6,40 +8,26 @@ # Default usage, this will give you offline access and a refresh token # using default scopes 'email' and 'profile' # - provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], { - :scope => 'email,profile' - } + provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'email,profile' # Manual setup for offline access with a refresh token. # - # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], { - # :access_type => 'offline', - # } + # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'offline' # Custom scope supporting youtube. If you are customizing scopes, remember # to include the default scopes 'email' and 'profile' # - # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], { - # :scope => 'http://gdata.youtube.com,email,profile,plus.me' - # } + # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'http://gdata.youtube.com,email,profile,plus.me' # Custom scope for users only using Google for account creation/auth and do not require a refresh token. # - # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], { - # :access_type => 'online', - # :prompt => '' - # } + # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'online', prompt: '' # To include information about people in your circles you must include the 'plus.login' scope. # - # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], { - # :skip_friends => false, - # :scope => "email,profile,plus.login" - # } + # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], skip_friends: false, scope: 'email,profile,plus.login' # If you need to acquire whether user picture is a default one or uploaded by user. # - # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], { - # :skip_image_info => false - # } + # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], skip_image_info: false end diff --git a/lib/omniauth-google-oauth2.rb b/lib/omniauth-google-oauth2.rb index 88ca8ca..a5cc57a 100644 --- a/lib/omniauth-google-oauth2.rb +++ b/lib/omniauth-google-oauth2.rb @@ -1 +1,3 @@ +# frozen_string_literal: true + require 'omniauth/google_oauth2' diff --git a/lib/omniauth/google_oauth2.rb b/lib/omniauth/google_oauth2.rb index 067a579..594c9a4 100644 --- a/lib/omniauth/google_oauth2.rb +++ b/lib/omniauth/google_oauth2.rb @@ -1 +1,3 @@ +# frozen_string_literal: true + require 'omniauth/strategies/google_oauth2' diff --git a/lib/omniauth/google_oauth2/version.rb b/lib/omniauth/google_oauth2/version.rb index e690c7b..91d41d0 100644 --- a/lib/omniauth/google_oauth2/version.rb +++ b/lib/omniauth/google_oauth2/version.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + module OmniAuth module GoogleOauth2 - VERSION = "0.5.0" + VERSION = '0.5.0' end end diff --git a/lib/omniauth/strategies/google_oauth2.rb b/lib/omniauth/strategies/google_oauth2.rb index d2a33e1..9d183b3 100644 --- a/lib/omniauth/strategies/google_oauth2.rb +++ b/lib/omniauth/strategies/google_oauth2.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'multi_json' require 'jwt' require 'omniauth/strategies/oauth2' @@ -5,24 +7,24 @@ module OmniAuth module Strategies + # Main class for Google OAuth2 strategy. class GoogleOauth2 < OmniAuth::Strategies::OAuth2 - BASE_SCOPE_URL = "https://www.googleapis.com/auth/" - BASE_SCOPES = %w[profile email openid] - DEFAULT_SCOPE = "email,profile" + BASE_SCOPE_URL = 'https://www.googleapis.com/auth/' + BASE_SCOPES = %w[profile email openid].freeze + DEFAULT_SCOPE = 'email,profile' option :name, 'google_oauth2' option :skip_friends, true option :skip_image_info, true option :skip_jwt, false option :jwt_leeway, 60 - option :authorize_options, [:access_type, :hd, :login_hint, :prompt, :request_visible_actions, :scope, :state, :redirect_uri, :include_granted_scopes, :openid_realm] + option :authorize_options, %i[access_type hd login_hint prompt request_visible_actions scope state redirect_uri include_granted_scopes openid_realm] option :authorized_client_ids, [] - option :client_options, { - :site => 'https://accounts.google.com', - :authorize_url => '/o/oauth2/auth', - :token_url => '/o/oauth2/token' - } + option :client_options, + site: 'https://accounts.google.com', + authorize_url: '/o/oauth2/auth', + token_url: '/o/oauth2/token' def authorize_params super.tap do |params| @@ -30,30 +32,27 @@ def authorize_params params[k] = request.params[k.to_s] unless [nil, ''].include?(request.params[k.to_s]) end - raw_scope = params[:scope] || DEFAULT_SCOPE - scope_list = raw_scope.split(" ").map {|item| item.split(",")}.flatten - scope_list.map! { |s| s =~ /^https?:\/\// || BASE_SCOPES.include?(s) ? s : "#{BASE_SCOPE_URL}#{s}" } - params[:scope] = scope_list.join(" ") + params[:scope] = get_scope(params) params[:access_type] = 'offline' if params[:access_type].nil? params['openid.realm'] = params.delete(:openid_realm) unless params[:openid_realm].nil? - session['omniauth.state'] = params[:state] if params['state'] + session['omniauth.state'] = params[:state] if params[:state] end end uid { raw_info['sub'] } info do - prune!({ - :name => raw_info['name'], - :email => verified_email, - :first_name => raw_info['given_name'], - :last_name => raw_info['family_name'], - :image => image_url, - :urls => { - 'Google' => raw_info['profile'] + prune!( + name: raw_info['name'], + email: verified_email, + first_name: raw_info['given_name'], + last_name: raw_info['family_name'], + image: image_url, + urls: { + google: raw_info['profile'] } - }) + ) end extra do @@ -61,18 +60,17 @@ def authorize_params hash[:id_token] = access_token['id_token'] if !options[:skip_jwt] && !access_token['id_token'].nil? hash[:id_info] = JWT.decode( - access_token['id_token'], nil, false, { - :verify_iss => true, - 'iss' => 'accounts.google.com', - :verify_aud => true, - 'aud' => options.client_id, - :verify_sub => false, - :verify_expiration => true, - :verify_not_before => true, - :verify_iat => true, - :verify_jti => false, - :leeway => options[:jwt_leeway] - }).first + access_token['id_token'], nil, false, verify_iss: true, + iss: 'accounts.google.com', + verify_aud: true, + aud: options.client_id, + verify_sub: false, + verify_expiration: true, + verify_not_before: true, + verify_iat: true, + verify_jti: false, + leeway: options[:jwt_leeway] + ).first end hash[:raw_info] = raw_info unless skip_info? hash[:raw_friend_info] = raw_friend_info(raw_info['sub']) unless skip_info? || options[:skip_friends] @@ -93,7 +91,20 @@ def raw_image_info(id) end def custom_build_access_token - access_token = + access_token = get_access_token(request) + + verify_hd(access_token) + access_token + end + alias build_access_token custom_build_access_token + + private + + def callback_url + options[:redirect_uri] || (full_host + script_name + callback_path) + end + + def get_access_token(request) if request.xhr? && request.params['code'] verifier = request.params['code'] redirect_uri = request.params['redirect_uri'] || 'postmessage' @@ -105,23 +116,20 @@ def custom_build_access_token elsif verify_token(request.params['access_token']) ::OAuth2::AccessToken.from_hash(client, request.params.dup) else - verifier = request.params["code"] + verifier = request.params['code'] client.auth_code.get_token(verifier, get_token_options(callback_url), deep_symbolize(options.auth_token_params)) end - - verify_hd(access_token) - access_token end - alias_method :build_access_token, :custom_build_access_token - private - - def callback_url - options[:redirect_uri] || (full_host + script_name + callback_path) + def get_scope(params) + raw_scope = params[:scope] || DEFAULT_SCOPE + scope_list = raw_scope.split(' ').map { |item| item.split(',') }.flatten + scope_list.map! { |s| s =~ %r{^https?://} || BASE_SCOPES.include?(s) ? s : "#{BASE_SCOPE_URL}#{s}" } + scope_list.join(' ') end def get_token_options(redirect_uri) - { :redirect_uri => redirect_uri }.merge(token_params.to_hash(:symbolize_keys => true)) + { redirect_uri: redirect_uri }.merge(token_params.to_hash(symbolize_keys: true)) end def prune!(hash) @@ -153,7 +161,7 @@ def image_url end def image_size_opts_passed? - !!(options[:image_size] || options[:image_aspect_ratio]) + options[:image_size] || options[:image_aspect_ratio] end def image_params @@ -174,7 +182,7 @@ def strip_unnecessary_query_parameters(query_parameters) return nil if query_parameters.nil? params = CGI.parse(query_parameters) - stripped_params = params.delete_if { |key| key == "sz" } + stripped_params = params.delete_if { |key| key == 'sz' } # don't return an empty Hash since that would result # in URLs with a trailing ? character: http://image.url? @@ -193,11 +201,11 @@ def verify_token(access_token) def verify_hd(access_token) return true unless options.hd @raw_info ||= access_token.get('https://www.googleapis.com/plus/v1/people/me/openIdConnect').parsed - + options.hd = options.hd.call if options.hd.is_a? Proc allowed_hosted_domains = Array(options.hd) - raise CallbackError.new(:invalid_hd, "Invalid Hosted Domain") unless allowed_hosted_domains.include? @raw_info['hd'] + raise CallbackError.new(:invalid_hd, 'Invalid Hosted Domain') unless allowed_hosted_domains.include? @raw_info['hd'] true end end diff --git a/omniauth-google-oauth2.gemspec b/omniauth-google-oauth2.gemspec index cb829d2..ab36193 100644 --- a/omniauth-google-oauth2.gemspec +++ b/omniauth-google-oauth2.gemspec @@ -1,26 +1,32 @@ # -*- encoding: utf-8 -*- -require File.expand_path(File.join('..', 'lib', 'omniauth', 'google_oauth2', 'version'), __FILE__) +# frozen_string_literal: true + +require File.expand_path( + File.join('..', 'lib', 'omniauth', 'google_oauth2', 'version'), + __FILE__ +) Gem::Specification.new do |gem| - gem.name = "omniauth-google-oauth2" + gem.name = 'omniauth-google-oauth2' gem.version = OmniAuth::GoogleOauth2::VERSION gem.license = 'MIT' - gem.summary = %q{A Google OAuth2 strategy for OmniAuth 1.x} - gem.description = %q{A Google OAuth2 strategy for OmniAuth 1.x} - gem.authors = ["Josh Ellithorpe", "Yury Korolev"] - gem.email = ["quest@mac.com"] - gem.homepage = "https://github.com/zquestz/omniauth-google-oauth2" + gem.summary = %(A Google OAuth2 strategy for OmniAuth 1.x) + gem.description = %(A Google OAuth2 strategy for OmniAuth 1.x. This allows you to login to Google with your ruby app.) + gem.authors = ['Josh Ellithorpe', 'Yury Korolev'] + gem.email = ['quest@mac.com'] + gem.homepage = 'https://github.com/zquestz/omniauth-google-oauth2' gem.files = `git ls-files`.split("\n") - gem.require_paths = ["lib"] + gem.require_paths = ['lib'] gem.required_ruby_version = '>= 2.0' gem.add_runtime_dependency 'omniauth', '>= 1.1.1' gem.add_runtime_dependency 'omniauth-oauth2', '>= 1.3.1' - gem.add_runtime_dependency 'jwt', '~> 1.5.2' + gem.add_runtime_dependency 'jwt', '~> 1.5' gem.add_runtime_dependency 'multi_json', '~> 1.3' - gem.add_development_dependency 'rspec', '>= 2.14.0' - gem.add_development_dependency 'rake' + gem.add_development_dependency 'rspec', '~> 3.6' + gem.add_development_dependency 'rake', '~> 12.0' + gem.add_development_dependency 'rubocop', '~> 0.49' end diff --git a/spec/omniauth/strategies/google_oauth2_spec.rb b/spec/omniauth/strategies/google_oauth2_spec.rb index 8b3103c..698ffcc 100644 --- a/spec/omniauth/strategies/google_oauth2_spec.rb +++ b/spec/omniauth/strategies/google_oauth2_spec.rb @@ -1,19 +1,21 @@ +# frozen_string_literal: true + require 'spec_helper' require 'omniauth-google-oauth2' describe OmniAuth::Strategies::GoogleOauth2 do - let(:request) { double('Request', :params => {}, :cookies => {}, :env => {}) } - let(:app) { + let(:request) { double('Request', params: {}, cookies: {}, env: {}) } + let(:app) do lambda do - [200, {}, ["Hello."]] + [200, {}, ['Hello.']] end - } + end subject do OmniAuth::Strategies::GoogleOauth2.new(app, 'appid', 'secret', @options || {}).tap do |strategy| - allow(strategy).to receive(:request) { + allow(strategy).to receive(:request) do request - } + end end end @@ -38,40 +40,59 @@ expect(subject.client.options[:token_url]).to eq('/o/oauth2/token') end - describe "overrides" do - it 'should allow overriding the site' do - @options = {:client_options => {'site' => 'https://example.com'}} - expect(subject.client.site).to eq('https://example.com') - end + describe 'overrides' do + context 'as strings' do + it 'should allow overriding the site' do + @options = { client_options: { 'site' => 'https://example.com' } } + expect(subject.client.site).to eq('https://example.com') + end - it 'should allow overriding the authorize_url' do - @options = {:client_options => {'authorize_url' => 'https://example.com'}} - expect(subject.client.options[:authorize_url]).to eq('https://example.com') + it 'should allow overriding the authorize_url' do + @options = { client_options: { 'authorize_url' => 'https://example.com' } } + expect(subject.client.options[:authorize_url]).to eq('https://example.com') + end + + it 'should allow overriding the token_url' do + @options = { client_options: { 'token_url' => 'https://example.com' } } + expect(subject.client.options[:token_url]).to eq('https://example.com') + end end - it 'should allow overriding the token_url' do - @options = {:client_options => {'token_url' => 'https://example.com'}} - expect(subject.client.options[:token_url]).to eq('https://example.com') + context 'as symbols' do + it 'should allow overriding the site' do + @options = { client_options: { site: 'https://example.com' } } + expect(subject.client.site).to eq('https://example.com') + end + + it 'should allow overriding the authorize_url' do + @options = { client_options: { authorize_url: 'https://example.com' } } + expect(subject.client.options[:authorize_url]).to eq('https://example.com') + end + + it 'should allow overriding the token_url' do + @options = { client_options: { token_url: 'https://example.com' } } + expect(subject.client.options[:token_url]).to eq('https://example.com') + end end end end - describe "#authorize_options" do - [:access_type, :hd, :login_hint, :prompt, :scope, :state].each do |k| + describe '#authorize_options' do + %i[access_type hd login_hint prompt scope state].each do |k| it "should support #{k}" do - @options = {k => 'http://someval'} + @options = { k => 'http://someval' } expect(subject.authorize_params[k.to_s]).to eq('http://someval') end end - describe "redirect_uri" do + describe 'redirect_uri' do it 'should default to nil' do @options = {} expect(subject.authorize_params['redirect_uri']).to eq(nil) end it 'should set the redirect_uri parameter if present' do - @options = {:redirect_uri => 'https://example.com'} + @options = { redirect_uri: 'https://example.com' } expect(subject.authorize_params['redirect_uri']).to eq('https://example.com') end end @@ -83,56 +104,56 @@ end it 'should set the access_type parameter if present' do - @options = {:access_type => 'online'} + @options = { access_type: 'online' } expect(subject.authorize_params['access_type']).to eq('online') end end describe 'hd' do - it "should default to nil" do + it 'should default to nil' do expect(subject.authorize_params['hd']).to eq(nil) end it 'should set the hd (hosted domain) parameter if present' do - @options = {:hd => 'example.com'} + @options = { hd: 'example.com' } expect(subject.authorize_params['hd']).to eq('example.com') end it 'should set the hd parameter and work with nil hd (gmail)' do - @options = {:hd => nil } + @options = { hd: nil } expect(subject.authorize_params['hd']).to eq(nil) end end describe 'login_hint' do - it "should default to nil" do + it 'should default to nil' do expect(subject.authorize_params['login_hint']).to eq(nil) end it 'should set the login_hint parameter if present' do - @options = {:login_hint => 'john@example.com'} + @options = { login_hint: 'john@example.com' } expect(subject.authorize_params['login_hint']).to eq('john@example.com') end end describe 'prompt' do - it "should default to nil" do + it 'should default to nil' do expect(subject.authorize_params['prompt']).to eq(nil) end it 'should set the prompt parameter if present' do - @options = {:prompt => 'consent select_account'} + @options = { prompt: 'consent select_account' } expect(subject.authorize_params['prompt']).to eq('consent select_account') end end describe 'request_visible_actions' do - it "should default to nil" do + it 'should default to nil' do expect(subject.authorize_params['request_visible_actions']).to eq(nil) end it 'should set the request_visible_actions parameter if present' do - @options = {:request_visible_actions => 'something'} + @options = { request_visible_actions: 'something' } expect(subject.authorize_params['request_visible_actions']).to eq('something') end end @@ -143,29 +164,29 @@ end it 'should set the include_granted_scopes parameter if present' do - @options = {:include_granted_scopes => 'true'} + @options = { include_granted_scopes: 'true' } expect(subject.authorize_params['include_granted_scopes']).to eq('true') end end describe 'scope' do it 'should expand scope shortcuts' do - @options = {:scope => 'plus.me'} + @options = { scope: 'plus.me' } expect(subject.authorize_params['scope']).to eq('https://www.googleapis.com/auth/plus.me') end it 'should leave base scopes as is' do - @options = {:scope => 'profile'} + @options = { scope: 'profile' } expect(subject.authorize_params['scope']).to eq('profile') end it 'should join scopes' do - @options = {:scope => 'profile,email'} + @options = { scope: 'profile,email' } expect(subject.authorize_params['scope']).to eq('profile email') end it 'should deal with whitespace when joining scopes' do - @options = {:scope => 'profile, email'} + @options = { scope: 'profile, email' } expect(subject.authorize_params['scope']).to eq('profile email') end @@ -174,56 +195,58 @@ end it 'should support space delimited scopes' do - @options = {:scope => 'profile email'} + @options = { scope: 'profile email' } expect(subject.authorize_params['scope']).to eq('profile email') end - it "should support extremely badly formed scopes" do - @options = {:scope => 'profile email,foo,steve yeah http://example.com'} + it 'should support extremely badly formed scopes' do + @options = { scope: 'profile email,foo,steve yeah http://example.com' } expect(subject.authorize_params['scope']).to eq('profile email https://www.googleapis.com/auth/foo https://www.googleapis.com/auth/steve https://www.googleapis.com/auth/yeah http://example.com') end end describe 'state' do it 'should set the state parameter' do - @options = {:state => 'some_state'} + @options = { state: 'some_state' } expect(subject.authorize_params['state']).to eq('some_state') + expect(subject.authorize_params[:state]).to eq('some_state') expect(subject.session['omniauth.state']).to eq('some_state') end it 'should set the omniauth.state dynamically' do - allow(subject).to receive(:request) { double('Request', {:params => {'state' => 'some_state'}, :env => {}}) } + allow(subject).to receive(:request) { double('Request', params: { 'state' => 'some_state' }, env: {}) } expect(subject.authorize_params['state']).to eq('some_state') + expect(subject.authorize_params[:state]).to eq('some_state') expect(subject.session['omniauth.state']).to eq('some_state') end end - describe "overrides" do + describe 'overrides' do it 'should include top-level options that are marked as :authorize_options' do - @options = {:authorize_options => [:scope, :foo, :request_visible_actions], :scope => 'http://bar', :foo => 'baz', :hd => "wow", :request_visible_actions => "something"} + @options = { authorize_options: %i[scope foo request_visible_actions], scope: 'http://bar', foo: 'baz', hd: 'wow', request_visible_actions: 'something' } expect(subject.authorize_params['scope']).to eq('http://bar') expect(subject.authorize_params['foo']).to eq('baz') expect(subject.authorize_params['hd']).to eq(nil) expect(subject.authorize_params['request_visible_actions']).to eq('something') end - describe "request overrides" do - [:access_type, :hd, :login_hint, :prompt, :scope, :state].each do |k| + describe 'request overrides' do + %i[access_type hd login_hint prompt scope state].each do |k| context "authorize option #{k}" do - let(:request) { double('Request', :params => {k.to_s => 'http://example.com'}, :cookies => {}, :env => {}) } + let(:request) { double('Request', params: { k.to_s => 'http://example.com' }, cookies: {}, env: {}) } it "should set the #{k} authorize option dynamically in the request" do - @options = {k => ''} + @options = { k: '' } expect(subject.authorize_params[k.to_s]).to eq('http://example.com') end end end - describe "custom authorize_options" do - let(:request) { double('Request', :params => {'foo' => 'something'}, :cookies => {}, :env => {}) } + describe 'custom authorize_options' do + let(:request) { double('Request', params: { 'foo' => 'something' }, cookies: {}, env: {}) } - it "should support request overrides from custom authorize_options" do - @options = {:authorize_options => [:foo], :foo => ''} + it 'should support request overrides from custom authorize_options' do + @options = { authorize_options: [:foo], foo: '' } expect(subject.authorize_params['foo']).to eq('something') end end @@ -233,7 +256,7 @@ describe '#authorize_params' do it 'should include any authorize params passed in the :authorize_params option' do - @options = {:authorize_params => {:request_visible_actions => 'something', :foo => 'bar', :baz => 'zip'}, :hd => 'wow', :bad => 'not_included'} + @options = { authorize_params: { request_visible_actions: 'something', foo: 'bar', baz: 'zip' }, hd: 'wow', bad: 'not_included' } expect(subject.authorize_params['request_visible_actions']).to eq('something') expect(subject.authorize_params['foo']).to eq('bar') expect(subject.authorize_params['baz']).to eq('zip') @@ -244,15 +267,15 @@ describe '#token_params' do it 'should include any token params passed in the :token_params option' do - @options = {:token_params => {:foo => 'bar', :baz => 'zip'}} + @options = { token_params: { foo: 'bar', baz: 'zip' } } expect(subject.token_params['foo']).to eq('bar') expect(subject.token_params['baz']).to eq('zip') end end - describe "#token_options" do + describe '#token_options' do it 'should include top-level options that are marked as :token_options' do - @options = {:token_options => [:scope, :foo], :scope => 'bar', :foo => 'baz', :bad => 'not_included'} + @options = { token_options: %i[scope foo], scope: 'bar', foo: 'baz', bad: 'not_included' } expect(subject.token_params['scope']).to eq('bar') expect(subject.token_params['foo']).to eq('baz') expect(subject.token_params['bad']).to eq(nil) @@ -265,10 +288,9 @@ end it 'should set the callback_path parameter if present' do - @options = {:callback_path => '/auth/foo/callback'} + @options = { callback_path: '/auth/foo/callback' } expect(subject.callback_path).to eq('/auth/foo/callback') end - end describe '#extra' do @@ -276,9 +298,9 @@ OAuth2::Client.new('abc', 'def') do |builder| builder.request :url_encoded builder.adapter :test do |stub| - stub.get('/plus/v1/people/me/openIdConnect') {|env| [200, {'content-type' => 'application/json'}, '{"sub": "12345"}']} - stub.get('/plus/v1/people/12345/people/visible') {|env| [200, {'content-type' => 'application/json'}, '[{"foo":"bar"}]']} - stub.get('/plus/v1/people/12345?fields=image') {|env| [200, {'content-type' => 'application/json'}, '{"image":"imageData"}']} + stub.get('/plus/v1/people/me/openIdConnect') { [200, { 'content-type' => 'application/json' }, '{"sub": "12345"}'] } + stub.get('/plus/v1/people/12345/people/visible') { [200, { 'content-type' => 'application/json' }, '[{"foo":"bar"}]'] } + stub.get('/plus/v1/people/12345?fields=image') { [200, { 'content-type' => 'application/json' }, '{"image":"imageData"}'] } end end end @@ -295,18 +317,18 @@ 'nbf' => Time.now.to_i - 60, 'iat' => Time.now.to_i, 'aud' => 'appid', - 'iss' => 'accounts.google.com', + 'iss' => 'accounts.google.com' } id_token = JWT.encode(token_info, 'secret') - let(:access_token) { OAuth2::AccessToken.from_hash(client, {'id_token' => id_token}) } + let(:access_token) { OAuth2::AccessToken.from_hash(client, 'id_token' => id_token) } it 'should include id_token when set on the access_token' do - expect(subject.extra).to include(:id_token => id_token) + expect(subject.extra).to include(id_token: id_token) end it 'should include id_info when id_token is set on the access_token and skip_jwt is false' do subject.options[:skip_jwt] = false - expect(subject.extra).to include(:id_info => token_info) + expect(subject.extra).to include(id_info: token_info) end it 'should not include id_info when id_token is set on the access_token and skip_jwt is true' do @@ -315,7 +337,7 @@ end it 'should include id_info when id_token is set on the access_token by default' do - expect(subject.extra).to include(:id_info => token_info) + expect(subject.extra).to include(id_info: token_info) end end @@ -372,7 +394,7 @@ before { subject.options[:skip_friends] = false } it 'should not include raw_friend_info' do - expect(subject.extra[:raw_friend_info]).to eq([{'foo' => 'bar'}]) + expect(subject.extra[:raw_friend_info]).to eq([{ 'foo' => 'bar' }]) end end end @@ -402,7 +424,7 @@ before { subject.options[:skip_image_info] = false } it 'should include raw_image_info' do - expect(subject.extra[:raw_image_info]).to eq({'image' => 'imageData'}) + expect(subject.extra[:raw_image_info]).to eq('image' => 'imageData') end end end @@ -411,92 +433,92 @@ describe 'populate auth hash urls' do it 'should populate url map in auth hash if link present in raw_info' do - allow(subject).to receive(:raw_info) { {'name' => 'Foo', 'profile' => 'https://plus.google.com/123456'} } - expect(subject.info[:urls]['Google']).to eq('https://plus.google.com/123456') + allow(subject).to receive(:raw_info) { { 'name' => 'Foo', 'profile' => 'https://plus.google.com/123456' } } + expect(subject.info[:urls][:google]).to eq('https://plus.google.com/123456') end it 'should not populate url map in auth hash if no link present in raw_info' do - allow(subject).to receive(:raw_info) { {'name' => 'Foo'} } + allow(subject).to receive(:raw_info) { { 'name' => 'Foo' } } expect(subject.info).not_to have_key(:urls) end end describe 'image options' do - it "should have no image if a picture isn't present" do - @options = {:image_aspect_ratio => 'square'} - allow(subject).to receive(:raw_info) { {'name' => 'User Without Pic'} } + it 'should have no image if a picture is not present' do + @options = { image_aspect_ratio: 'square' } + allow(subject).to receive(:raw_info) { { 'name' => 'User Without Pic' } } expect(subject.info[:image]).to be_nil end - describe "when a picture is returned from google" do + describe 'when a picture is returned from google' do it 'should return the image with size specified in the `image_size` option' do - @options = {:image_size => 50} - allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} } + @options = { 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/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'} } + @options = { 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/photo.jpg') end it 'should handle a picture with a size query parameter correctly' do - @options = {:image_size => 50} - allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50'} } + @options = { image_size: 50 } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50' } } expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg') end it 'should handle a picture with a size query parameter and other valid query parameters correctly' do - @options = {:image_size => 50} - allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50&hello=true&life=42'} } + @options = { image_size: 50 } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50&hello=true&life=42' } } expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg?hello=true&life=42') end it 'should handle a picture with other valid query parameters correctly' do - @options = {:image_size => 50} - allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?hello=true&life=42'} } + @options = { image_size: 50 } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?hello=true&life=42' } } expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg?hello=true&life=42') end it 'should return the image with width and height specified in the `image_size` option' do - @options = {:image_size => {:width => 50, :height => 40}} - allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} } + @options = { 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/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'} } + @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 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'} } + @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` 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'} } + @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 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'} } + @options = { image_size: 50 } + allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photograph.jpg' } } expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/photograph.jpg') end end it 'should return original image if no options are provided' do - allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} } + 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/photo.jpg') end it 'should return correct image if google image url has double https' do - allow(subject).to receive(:raw_info) { {'picture' => 'https:https://lh3.googleusercontent.com/url/photo.jpg'} } + allow(subject).to receive(:raw_info) { { 'picture' => 'https:https://lh3.googleusercontent.com/url/photo.jpg' } } expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/photo.jpg') end end @@ -510,7 +532,7 @@ auth_code = double(:auth_code) allow(client).to receive(:auth_code).and_return(auth_code) expect(subject).to receive(:client).and_return(client) - expect(auth_code).to receive(:get_token).with('valid_code', { :redirect_uri => 'postmessage'}, {}) + expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'postmessage' }, {}) expect(subject).not_to receive(:orig_build_access_token) subject.build_access_token @@ -524,7 +546,7 @@ auth_code = double(:auth_code) allow(client).to receive(:auth_code).and_return(auth_code) expect(subject).to receive(:client).and_return(client) - expect(auth_code).to receive(:get_token).with('valid_code', { :redirect_uri => ''}, {}) + expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: '' }, {}) expect(subject).not_to receive(:orig_build_access_token) subject.build_access_token @@ -538,7 +560,7 @@ auth_code = double(:auth_code) allow(client).to receive(:auth_code).and_return(auth_code) expect(subject).to receive(:client).and_return(client) - expect(auth_code).to receive(:get_token).with('valid_code', { :redirect_uri => 'redirect_uri'}, {}) + expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'redirect_uri' }, {}) expect(subject).not_to receive(:orig_build_access_token) subject.build_access_token @@ -566,7 +588,7 @@ allow(subject).to receive(:callback_url).and_return('redirect_uri_without_query_string') expect(subject).to receive(:client).and_return(client) - expect(auth_code).to receive(:get_token).with('valid_code', { :redirect_uri => 'redirect_uri_without_query_string'}, {}) + expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'redirect_uri_without_query_string' }, {}) subject.build_access_token end end @@ -576,19 +598,19 @@ 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 |env| - [200, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode( - :aud => "000000000000.apps.googleusercontent.com", - :sub => "123456789", - :email_verified => "true", - :email => "example@example.com", - :access_type => "offline", - :scope => "profile email", - :expires_in => 436 + stub.get('/oauth2/v3/tokeninfo?access_token=valid_access_token') do + [200, { 'Content-Type' => 'application/json; charset=UTF-8' }, MultiJson.encode( + aud: '000000000000.apps.googleusercontent.com', + sub: '123456789', + email_verified: 'true', + email: 'example@example.com', + access_type: 'offline', + scope: 'profile email', + expires_in: 436 )] end - stub.get('/oauth2/v3/tokeninfo?access_token=invalid_access_token') do |env| - [400, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode(:error_description => 'Invalid Value')] + stub.get('/oauth2/v3/tokeninfo?access_token=invalid_access_token') do + [400, { 'Content-Type' => 'application/json; charset=UTF-8' }, MultiJson.encode(error_description: 'Invalid Value')] end end end @@ -600,7 +622,7 @@ end it 'should verify token if access_token is valid and app_id authorized' do - subject.options.authorized_client_ids = ["000000000000.apps.googleusercontent.com"] + subject.options.authorized_client_ids = ['000000000000.apps.googleusercontent.com'] expect(subject.send(:verify_token, 'valid_access_token')).to eq(true) end @@ -609,9 +631,9 @@ end it 'should raise error if access_token is invalid' do - expect { + expect do subject.send(:verify_token, 'invalid_access_token') - }.to raise_error(OAuth2::Error) + end.to raise_error(OAuth2::Error) end end @@ -620,9 +642,9 @@ OAuth2::Client.new('abc', 'def') do |builder| builder.request :url_encoded builder.adapter :test do |stub| - stub.get('/plus/v1/people/me/openIdConnect') do |env| - [200, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode( - :hd => 'example.com', + stub.get('/plus/v1/people/me/openIdConnect') do + [200, { 'Content-Type' => 'application/json; charset=UTF-8' }, MultiJson.encode( + hd: 'example.com' )] end end @@ -635,8 +657,8 @@ OAuth2::Client.new('abc', 'def') do |builder| builder.request :url_encoded builder.adapter :test do |stub| - stub.get('/plus/v1/people/me/openIdConnect') do |env| - [200, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode({})] + stub.get('/plus/v1/people/me/openIdConnect') do + [200, { 'Content-Type' => 'application/json; charset=UTF-8' }, MultiJson.encode({})] end end end @@ -654,9 +676,9 @@ it 'should raise an exception if nil is not included' do subject.options.hd = ['example.com', 'example.co'] - expect { + expect do subject.send(:verify_hd, access_token) - }.to raise_error(OmniAuth::Strategies::OAuth2::CallbackError) + end.to raise_error(OmniAuth::Strategies::OAuth2::CallbackError) end end @@ -673,29 +695,29 @@ subject.options.hd = ['example.com', 'example.co', nil] expect(subject.send(:verify_hd, access_token)).to eq(true) end - + it 'should verify hd if options hd is set as an Proc and is correct' do - subject.options.hd = Proc.new { 'example.com' } + subject.options.hd = proc { 'example.com' } expect(subject.send(:verify_hd, access_token)).to eq(true) end - + it 'should verify hd if options hd is set as an Proc returning an array and is correct' do - subject.options.hd = Proc.new { ['example.com', 'example.co'] } + subject.options.hd = proc { ['example.com', 'example.co'] } expect(subject.send(:verify_hd, access_token)).to eq(true) end it 'should raise error if options hd is set and wrong' do subject.options.hd = 'invalid.com' - expect { + expect do subject.send(:verify_hd, access_token) - }.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError) + end.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError) end it 'should raise error if options hd is set as an array and is not correct' do subject.options.hd = ['invalid.com', 'invalid.co'] - expect { + expect do subject.send(:verify_hd, access_token) - }.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError) + end.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError) end end end diff --git a/spec/rubocop_spec.rb b/spec/rubocop_spec.rb new file mode 100644 index 0000000..eca9b45 --- /dev/null +++ b/spec/rubocop_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require_relative 'spec_helper' + +describe 'Rubocop' do + it 'should pass with no offenses detected' do + expect(`rubocop`).to include('no offenses detected') + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9d08904..3c23253 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + require File.join('bundler', 'setup') -require 'rspec' \ No newline at end of file +require 'rspec'