added ruby 2.3 compatability
also: * updated rubocop and applied styling * made small test refactorings (using the expect block notation) * made a small refactor to remove an unnecessary ``return credentials`` * bumped the version
This commit is contained in:
1 parent
72fb8df541
commit
82a4f8520c
25 files changed
+199
-160
No files matched your search
+10
-10
@@ -34,12 +34,12 @@ module Google
|
||||
# Representation of an application's identity for user authorization
|
||||
# flows.
|
||||
class ClientId
|
||||
INSTALLED_APP = 'installed'
|
||||
WEB_APP = 'web'
|
||||
CLIENT_ID = 'client_id'
|
||||
CLIENT_SECRET = 'client_secret'
|
||||
INSTALLED_APP = 'installed'.freeze
|
||||
WEB_APP = 'web'.freeze
|
||||
CLIENT_ID = 'client_id'.freeze
|
||||
CLIENT_SECRET = 'client_secret'.freeze
|
||||
MISSING_TOP_LEVEL_ELEMENT_ERROR =
|
||||
"Expected top level property 'installed' or 'web' to be present."
|
||||
"Expected top level property 'installed' or 'web' to be present.".freeze
|
||||
|
||||
# Text identifier of the client ID
|
||||
# @return [String]
|
||||
@@ -63,8 +63,8 @@ module Google
|
||||
# & secrets in source. See {#from_file} to load from
|
||||
# `client_secrets.json` files.
|
||||
def initialize(id, secret)
|
||||
fail 'Client id can not be nil' if id.nil?
|
||||
fail 'Client secret can not be nil' if secret.nil?
|
||||
raise 'Client id can not be nil' if id.nil?
|
||||
raise 'Client secret can not be nil' if secret.nil?
|
||||
@id = id
|
||||
@secret = secret
|
||||
end
|
||||
@@ -76,7 +76,7 @@ module Google
|
||||
# Path of file to read from
|
||||
# @return [Google::Auth::ClientID]
|
||||
def self.from_file(file)
|
||||
fail 'File can not be nil.' if file.nil?
|
||||
raise 'File can not be nil.' if file.nil?
|
||||
File.open(file.to_s) do |f|
|
||||
json = f.read
|
||||
config = MultiJson.load(json)
|
||||
@@ -92,9 +92,9 @@ module Google
|
||||
# Parsed contents of the JSON file
|
||||
# @return [Google::Auth::ClientID]
|
||||
def self.from_hash(config)
|
||||
fail 'Hash can not be nil.' if config.nil?
|
||||
raise 'Hash can not be nil.' if config.nil?
|
||||
raw_detail = config[INSTALLED_APP] || config[WEB_APP]
|
||||
fail MISSING_TOP_LEVEL_ELEMENT_ERROR if raw_detail.nil?
|
||||
raise MISSING_TOP_LEVEL_ELEMENT_ERROR if raw_detail.nil?
|
||||
ClientId.new(raw_detail[CLIENT_ID], raw_detail[CLIENT_SECRET])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,13 +35,13 @@ module Google
|
||||
# Module Auth provides classes that provide Google-specific authorization
|
||||
# used to access Google APIs.
|
||||
module Auth
|
||||
NO_METADATA_SERVER_ERROR = <<END
|
||||
NO_METADATA_SERVER_ERROR = <<END.freeze
|
||||
Error code 404 trying to get security access token
|
||||
from Compute Engine metadata for the default service account. This
|
||||
may be because the virtual machine instance does not have permission
|
||||
scopes specified.
|
||||
END
|
||||
UNEXPECTED_ERROR_SUFFIX = <<END
|
||||
UNEXPECTED_ERROR_SUFFIX = <<END.freeze
|
||||
trying to get security access token from Compute Engine metadata for
|
||||
the default service account
|
||||
END
|
||||
@@ -52,8 +52,8 @@ END
|
||||
# The IP Address is used in the URIs to speed up failures on non-GCE
|
||||
# systems.
|
||||
COMPUTE_AUTH_TOKEN_URI = 'http://169.254.169.254/computeMetadata/v1/'\
|
||||
'instance/service-accounts/default/token'
|
||||
COMPUTE_CHECK_URI = 'http://169.254.169.254'
|
||||
'instance/service-accounts/default/token'.freeze
|
||||
COMPUTE_CHECK_URI = 'http://169.254.169.254'.freeze
|
||||
|
||||
class << self
|
||||
extend Memoist
|
||||
@@ -94,10 +94,10 @@ END
|
||||
Signet::OAuth2.parse_credentials(resp.body,
|
||||
resp.headers['content-type'])
|
||||
when 404
|
||||
fail(Signet::AuthorizationError, NO_METADATA_SERVER_ERROR)
|
||||
raise(Signet::AuthorizationError, NO_METADATA_SERVER_ERROR)
|
||||
else
|
||||
msg = "Unexpected error code #{resp.status}" + UNEXPECTED_ERROR_SUFFIX
|
||||
fail(Signet::AuthorizationError, msg)
|
||||
raise(Signet::AuthorizationError, msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,22 +39,23 @@ module Google
|
||||
# credentials files on the file system.
|
||||
module CredentialsLoader
|
||||
extend Memoist
|
||||
ENV_VAR = 'GOOGLE_APPLICATION_CREDENTIALS'
|
||||
ENV_VAR = 'GOOGLE_APPLICATION_CREDENTIALS'.freeze
|
||||
|
||||
PRIVATE_KEY_VAR = 'GOOGLE_PRIVATE_KEY'
|
||||
CLIENT_EMAIL_VAR = 'GOOGLE_CLIENT_EMAIL'
|
||||
CLIENT_ID_VAR = 'GOOGLE_CLIENT_ID'
|
||||
CLIENT_SECRET_VAR = 'GOOGLE_CLIENT_SECRET'
|
||||
REFRESH_TOKEN_VAR = 'GOOGLE_REFRESH_TOKEN'
|
||||
ACCOUNT_TYPE_VAR = 'GOOGLE_ACCOUNT_TYPE'
|
||||
PRIVATE_KEY_VAR = 'GOOGLE_PRIVATE_KEY'.freeze
|
||||
CLIENT_EMAIL_VAR = 'GOOGLE_CLIENT_EMAIL'.freeze
|
||||
CLIENT_ID_VAR = 'GOOGLE_CLIENT_ID'.freeze
|
||||
CLIENT_SECRET_VAR = 'GOOGLE_CLIENT_SECRET'.freeze
|
||||
REFRESH_TOKEN_VAR = 'GOOGLE_REFRESH_TOKEN'.freeze
|
||||
ACCOUNT_TYPE_VAR = 'GOOGLE_ACCOUNT_TYPE'.freeze
|
||||
|
||||
CREDENTIALS_FILE_NAME = 'application_default_credentials.json'
|
||||
CREDENTIALS_FILE_NAME = 'application_default_credentials.json'.freeze
|
||||
NOT_FOUND_ERROR =
|
||||
"Unable to read the credential file specified by #{ENV_VAR}"
|
||||
WELL_KNOWN_PATH = "gcloud/#{CREDENTIALS_FILE_NAME}"
|
||||
WELL_KNOWN_ERROR = 'Unable to read the default credential file'
|
||||
"Unable to read the credential file specified by #{ENV_VAR}".freeze
|
||||
WELL_KNOWN_PATH = "gcloud/#{CREDENTIALS_FILE_NAME}".freeze
|
||||
WELL_KNOWN_ERROR = 'Unable to read the default credential file'.freeze
|
||||
|
||||
SYSTEM_DEFAULT_ERROR = 'Unable to read the system default credential file'
|
||||
SYSTEM_DEFAULT_ERROR =
|
||||
'Unable to read the system default credential file'.freeze
|
||||
|
||||
# make_creds proxies the construction of a credentials instance
|
||||
#
|
||||
@@ -71,7 +72,7 @@ module Google
|
||||
def from_env(scope = nil)
|
||||
if ENV.key?(ENV_VAR)
|
||||
path = ENV[ENV_VAR]
|
||||
fail "file #{path} does not exist" unless File.exist?(path)
|
||||
raise "file #{path} does not exist" unless File.exist?(path)
|
||||
File.open(path) do |f|
|
||||
return make_creds(json_key_io: f, scope: scope)
|
||||
end
|
||||
|
||||
@@ -37,16 +37,16 @@ module Google
|
||||
module Auth
|
||||
# Authenticates requests using IAM credentials.
|
||||
class IAMCredentials
|
||||
SELECTOR_KEY = 'x-goog-iam-authority-selector'
|
||||
TOKEN_KEY = 'x-goog-iam-authorization-token'
|
||||
SELECTOR_KEY = 'x-goog-iam-authority-selector'.freeze
|
||||
TOKEN_KEY = 'x-goog-iam-authorization-token'.freeze
|
||||
|
||||
# Initializes an IAMCredentials.
|
||||
#
|
||||
# @param selector the IAM selector.
|
||||
# @param token the IAM token.
|
||||
def initialize(selector, token)
|
||||
fail TypeError unless selector.is_a? String
|
||||
fail TypeError unless token.is_a? String
|
||||
raise TypeError unless selector.is_a? String
|
||||
raise TypeError unless token.is_a? String
|
||||
@selector = selector
|
||||
@token = token
|
||||
end
|
||||
|
||||
@@ -39,7 +39,7 @@ module Google
|
||||
'email' => 'https://www.googleapis.com/auth/userinfo.email',
|
||||
'profile' => 'https://www.googleapis.com/auth/userinfo.profile',
|
||||
'openid' => 'https://www.googleapis.com/auth/plus.me'
|
||||
}
|
||||
}.freeze
|
||||
|
||||
def self.normalize(scope)
|
||||
list = as_array(scope)
|
||||
@@ -53,7 +53,7 @@ module Google
|
||||
when String
|
||||
scope.split(' ')
|
||||
else
|
||||
fail 'Invalid scope value. Must be string or array'
|
||||
raise 'Invalid scope value. Must be string or array'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -46,7 +46,7 @@ module Google
|
||||
#
|
||||
# cf [Application Default Credentials](http://goo.gl/mkAHpZ)
|
||||
class ServiceAccountCredentials < Signet::OAuth2::Client
|
||||
TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token'
|
||||
TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token'.freeze
|
||||
extend CredentialsLoader
|
||||
|
||||
# Creates a ServiceAccountCredentials.
|
||||
@@ -73,8 +73,8 @@ module Google
|
||||
# JSON key.
|
||||
def self.read_json_key(json_key_io)
|
||||
json_key = MultiJson.load(json_key_io.read)
|
||||
fail 'missing client_email' unless json_key.key?('client_email')
|
||||
fail 'missing private_key' unless json_key.key?('private_key')
|
||||
raise 'missing client_email' unless json_key.key?('client_email')
|
||||
raise 'missing private_key' unless json_key.key?('private_key')
|
||||
[json_key['private_key'], json_key['client_email']]
|
||||
end
|
||||
|
||||
@@ -119,8 +119,8 @@ module Google
|
||||
class ServiceAccountJwtHeaderCredentials
|
||||
JWT_AUD_URI_KEY = :jwt_aud_uri
|
||||
AUTH_METADATA_KEY = Signet::OAuth2::AUTH_METADATA_KEY
|
||||
TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token'
|
||||
SIGNING_ALGORITHM = 'RS256'
|
||||
TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token'.freeze
|
||||
SIGNING_ALGORITHM = 'RS256'.freeze
|
||||
EXPIRY = 60
|
||||
extend CredentialsLoader
|
||||
|
||||
@@ -139,8 +139,8 @@ module Google
|
||||
# JSON key.
|
||||
def self.read_json_key(json_key_io)
|
||||
json_key = MultiJson.load(json_key_io.read)
|
||||
fail 'missing client_email' unless json_key.key?('client_email')
|
||||
fail 'missing private_key' unless json_key.key?('private_key')
|
||||
raise 'missing client_email' unless json_key.key?('client_email')
|
||||
raise 'missing private_key' unless json_key.key?('private_key')
|
||||
[json_key['private_key'], json_key['client_email']]
|
||||
end
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ module Signet
|
||||
@refresh_listeners << block
|
||||
end
|
||||
|
||||
alias_method :orig_fetch_access_token!, :fetch_access_token!
|
||||
alias orig_fetch_access_token! fetch_access_token!
|
||||
def fetch_access_token!(options = {})
|
||||
info = orig_fetch_access_token!(options)
|
||||
notify_refresh_listeners
|
||||
|
||||
@@ -37,7 +37,7 @@ module Google
|
||||
# are stored as JSON using the supplied key, prefixed with
|
||||
# `g-user-token:`
|
||||
class RedisTokenStore < Google::Auth::TokenStore
|
||||
DEFAULT_KEY_PREFIX = 'g-user-token:'
|
||||
DEFAULT_KEY_PREFIX = 'g-user-token:'.freeze
|
||||
|
||||
# Create a new store with the supplied redis client.
|
||||
#
|
||||
@@ -51,12 +51,12 @@ module Google
|
||||
def initialize(options = {})
|
||||
redis = options.delete(:redis)
|
||||
prefix = options.delete(:prefix)
|
||||
case redis
|
||||
when Redis
|
||||
@redis = redis
|
||||
else
|
||||
@redis = Redis.new(options)
|
||||
end
|
||||
@redis = case redis
|
||||
when Redis
|
||||
redis
|
||||
else
|
||||
Redis.new(options)
|
||||
end
|
||||
@prefix = prefix || DEFAULT_KEY_PREFIX
|
||||
end
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ module Google
|
||||
# @return [String]
|
||||
# The loaded token data.
|
||||
def load(_id)
|
||||
fail 'Not implemented'
|
||||
raise 'Not implemented'
|
||||
end
|
||||
|
||||
# Put the token data into storage for the given ID.
|
||||
@@ -54,7 +54,7 @@ module Google
|
||||
# @param [String] token
|
||||
# The token data to store.
|
||||
def store(_id, _token)
|
||||
fail 'Not implemented'
|
||||
raise 'Not implemented'
|
||||
end
|
||||
|
||||
# Remove the token data from storage for the given ID.
|
||||
@@ -62,7 +62,7 @@ module Google
|
||||
# @param [String] id
|
||||
# ID of the token data to delete
|
||||
def delete(_id)
|
||||
fail 'Not implemented'
|
||||
raise 'Not implemented'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,6 +32,7 @@ require 'multi_json'
|
||||
require 'googleauth/signet'
|
||||
require 'googleauth/user_refresh'
|
||||
|
||||
# rubocop:disable ClassLength
|
||||
module Google
|
||||
module Auth
|
||||
# Handles an interactive 3-Legged-OAuth2 (3LO) user consent authorization.
|
||||
@@ -53,13 +54,13 @@ module Google
|
||||
# ...
|
||||
class UserAuthorizer
|
||||
MISMATCHED_CLIENT_ID_ERROR =
|
||||
'Token client ID of %s does not match configured client id %s'
|
||||
NIL_CLIENT_ID_ERROR = 'Client id can not be nil.'
|
||||
NIL_SCOPE_ERROR = 'Scope can not be nil.'
|
||||
NIL_USER_ID_ERROR = 'User ID can not be nil.'
|
||||
NIL_TOKEN_STORE_ERROR = 'Can not call method if token store is nil'
|
||||
'Token client ID of %s does not match configured client id %s'.freeze
|
||||
NIL_CLIENT_ID_ERROR = 'Client id can not be nil.'.freeze
|
||||
NIL_SCOPE_ERROR = 'Scope can not be nil.'.freeze
|
||||
NIL_USER_ID_ERROR = 'User ID can not be nil.'.freeze
|
||||
NIL_TOKEN_STORE_ERROR = 'Can not call method if token store is nil'.freeze
|
||||
MISSING_ABSOLUTE_URL_ERROR =
|
||||
'Absolute base url required for relative callback url "%s"'
|
||||
'Absolute base url required for relative callback url "%s"'.freeze
|
||||
|
||||
# Initialize the authorizer
|
||||
#
|
||||
@@ -73,8 +74,8 @@ module Google
|
||||
# URL (either absolute or relative) of the auth callback.
|
||||
# Defaults to '/oauth2callback'
|
||||
def initialize(client_id, scope, token_store, callback_uri = nil)
|
||||
fail NIL_CLIENT_ID_ERROR if client_id.nil?
|
||||
fail NIL_SCOPE_ERROR if scope.nil?
|
||||
raise NIL_CLIENT_ID_ERROR if client_id.nil?
|
||||
raise NIL_SCOPE_ERROR if scope.nil?
|
||||
|
||||
@client_id = client_id
|
||||
@scope = Array(scope)
|
||||
@@ -102,7 +103,8 @@ module Google
|
||||
credentials = UserRefreshCredentials.new(
|
||||
client_id: @client_id.id,
|
||||
client_secret: @client_id.secret,
|
||||
scope: scope)
|
||||
scope: scope
|
||||
)
|
||||
redirect_uri = redirect_uri_for(options[:base_url])
|
||||
url = credentials.authorization_uri(access_type: 'offline',
|
||||
redirect_uri: redirect_uri,
|
||||
@@ -123,8 +125,8 @@ module Google
|
||||
# @return [Google::Auth::UserRefreshCredentials]
|
||||
# Stored credentials, nil if none present
|
||||
def get_credentials(user_id, scope = nil)
|
||||
fail NIL_USER_ID_ERROR if user_id.nil?
|
||||
fail NIL_TOKEN_STORE_ERROR if @token_store.nil?
|
||||
raise NIL_USER_ID_ERROR if user_id.nil?
|
||||
raise NIL_TOKEN_STORE_ERROR if @token_store.nil?
|
||||
|
||||
scope ||= @scope
|
||||
saved_token = @token_store.load(user_id)
|
||||
@@ -132,8 +134,8 @@ module Google
|
||||
data = MultiJson.load(saved_token)
|
||||
|
||||
if data.fetch('client_id', @client_id.id) != @client_id.id
|
||||
fail sprintf(MISMATCHED_CLIENT_ID_ERROR,
|
||||
data['client_id'], @client_id.id)
|
||||
raise sprintf(MISMATCHED_CLIENT_ID_ERROR,
|
||||
data['client_id'], @client_id.id)
|
||||
end
|
||||
|
||||
credentials = UserRefreshCredentials.new(
|
||||
@@ -142,10 +144,10 @@ module Google
|
||||
scope: data['scope'] || @scope,
|
||||
access_token: data['access_token'],
|
||||
refresh_token: data['refresh_token'],
|
||||
expires_at: data.fetch('expiration_time_millis', 0) / 1000)
|
||||
expires_at: data.fetch('expiration_time_millis', 0) / 1000
|
||||
)
|
||||
if credentials.includes_scope?(scope)
|
||||
monitor_credentials(user_id, credentials)
|
||||
return credentials
|
||||
return monitor_credentials(user_id, credentials)
|
||||
end
|
||||
nil
|
||||
end
|
||||
@@ -174,7 +176,8 @@ module Google
|
||||
client_id: @client_id.id,
|
||||
client_secret: @client_id.secret,
|
||||
redirect_uri: redirect_uri_for(base_url),
|
||||
scope: scope)
|
||||
scope: scope
|
||||
)
|
||||
credentials.code = code
|
||||
credentials.fetch_access_token!({})
|
||||
monitor_credentials(user_id, credentials)
|
||||
@@ -234,7 +237,8 @@ module Google
|
||||
access_token: credentials.access_token,
|
||||
refresh_token: credentials.refresh_token,
|
||||
scope: credentials.scope,
|
||||
expiration_time_millis: (credentials.expires_at.to_i) * 1000)
|
||||
expiration_time_millis: credentials.expires_at.to_i * 1000
|
||||
)
|
||||
@token_store.store(user_id, json)
|
||||
credentials
|
||||
end
|
||||
@@ -263,11 +267,13 @@ module Google
|
||||
# Redirect URI
|
||||
def redirect_uri_for(base_url)
|
||||
return @callback_uri unless URI(@callback_uri).scheme.nil?
|
||||
fail sprintf(
|
||||
raise sprintf(
|
||||
MISSING_ABSOLUTE_URL_ERROR,
|
||||
@callback_uri) if base_url.nil? || URI(base_url).scheme.nil?
|
||||
@callback_uri
|
||||
) if base_url.nil? || URI(base_url).scheme.nil?
|
||||
URI.join(base_url, @callback_uri).to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable ClassLength
|
||||
@@ -46,9 +46,9 @@ module Google
|
||||
#
|
||||
# cf [Application Default Credentials](http://goo.gl/mkAHpZ)
|
||||
class UserRefreshCredentials < Signet::OAuth2::Client
|
||||
TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token'
|
||||
AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/auth'
|
||||
REVOKE_TOKEN_URI = 'https://accounts.google.com/o/oauth2/revoke'
|
||||
TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token'.freeze
|
||||
AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/auth'.freeze
|
||||
REVOKE_TOKEN_URI = 'https://accounts.google.com/o/oauth2/revoke'.freeze
|
||||
extend CredentialsLoader
|
||||
|
||||
# Create a UserRefreshCredentials.
|
||||
@@ -77,7 +77,7 @@ module Google
|
||||
json_key = MultiJson.load(json_key_io.read)
|
||||
wanted = %w(client_id client_secret refresh_token)
|
||||
wanted.each do |key|
|
||||
fail "the json is missing the #{key} field" unless json_key.key?(key)
|
||||
raise "the json is missing the #{key} field" unless json_key.key?(key)
|
||||
end
|
||||
json_key
|
||||
end
|
||||
@@ -99,8 +99,8 @@ module Google
|
||||
self.refresh_token = nil
|
||||
self.expires_at = 0
|
||||
else
|
||||
fail(Signet::AuthorizationError,
|
||||
"Unexpected error code #{resp.status}")
|
||||
raise(Signet::AuthorizationError,
|
||||
"Unexpected error code #{resp.status}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -31,6 +31,6 @@ module Google
|
||||
# Module Auth provides classes that provide Google-specific authorization
|
||||
# used to access Google APIs.
|
||||
module Auth
|
||||
VERSION = '0.5.1'
|
||||
VERSION = '0.5.2'.freeze
|
||||
end
|
||||
end
|
||||
@@ -66,20 +66,21 @@ module Google
|
||||
# @see {Google::Auth::ControllerHelpers}
|
||||
# @note Requires sessions are enabled
|
||||
class WebUserAuthorizer < Google::Auth::UserAuthorizer
|
||||
STATE_PARAM = 'state'
|
||||
AUTH_CODE_KEY = 'code'
|
||||
ERROR_CODE_KEY = 'error'
|
||||
SESSION_ID_KEY = 'session_id'
|
||||
CALLBACK_STATE_KEY = 'g-auth-callback'
|
||||
CURRENT_URI_KEY = 'current_uri'
|
||||
XSRF_KEY = 'g-xsrf-token'
|
||||
SCOPE_KEY = 'scope'
|
||||
STATE_PARAM = 'state'.freeze
|
||||
AUTH_CODE_KEY = 'code'.freeze
|
||||
ERROR_CODE_KEY = 'error'.freeze
|
||||
SESSION_ID_KEY = 'session_id'.freeze
|
||||
CALLBACK_STATE_KEY = 'g-auth-callback'.freeze
|
||||
CURRENT_URI_KEY = 'current_uri'.freeze
|
||||
XSRF_KEY = 'g-xsrf-token'.freeze
|
||||
SCOPE_KEY = 'scope'.freeze
|
||||
|
||||
NIL_REQUEST_ERROR = 'Request is required.'
|
||||
NIL_SESSION_ERROR = 'Sessions must be enabled'
|
||||
MISSING_AUTH_CODE_ERROR = 'Missing authorization code in request'
|
||||
AUTHORIZATION_ERROR = 'Authorization error: %s'
|
||||
INVALID_STATE_TOKEN_ERROR = 'State token does not match expected value'
|
||||
NIL_REQUEST_ERROR = 'Request is required.'.freeze
|
||||
NIL_SESSION_ERROR = 'Sessions must be enabled'.freeze
|
||||
MISSING_AUTH_CODE_ERROR = 'Missing authorization code in request'.freeze
|
||||
AUTHORIZATION_ERROR = 'Authorization error: %s'.freeze
|
||||
INVALID_STATE_TOKEN_ERROR =
|
||||
'State token does not match expected value'.freeze
|
||||
|
||||
class << self
|
||||
attr_accessor :default
|
||||
@@ -128,13 +129,15 @@ module Google
|
||||
# credentials & next URL to redirect to
|
||||
def handle_auth_callback(user_id, request)
|
||||
callback_state, redirect_uri = WebUserAuthorizer.extract_callback_state(
|
||||
request)
|
||||
request
|
||||
)
|
||||
WebUserAuthorizer.validate_callback_state(callback_state, request)
|
||||
credentials = get_and_store_credentials_from_code(
|
||||
user_id: user_id,
|
||||
code: callback_state[AUTH_CODE_KEY],
|
||||
scope: callback_state[SCOPE_KEY],
|
||||
base_url: request.url)
|
||||
base_url: request.url
|
||||
)
|
||||
[credentials, redirect_uri]
|
||||
end
|
||||
|
||||
@@ -156,14 +159,15 @@ module Google
|
||||
def get_authorization_url(options = {})
|
||||
options = options.dup
|
||||
request = options[:request]
|
||||
fail NIL_REQUEST_ERROR if request.nil?
|
||||
fail NIL_SESSION_ERROR if request.session.nil?
|
||||
raise NIL_REQUEST_ERROR if request.nil?
|
||||
raise NIL_SESSION_ERROR if request.session.nil?
|
||||
|
||||
redirect_to = options[:redirect_to] || request.url
|
||||
request.session[XSRF_KEY] = SecureRandom.base64
|
||||
options[:state] = MultiJson.dump(
|
||||
SESSION_ID_KEY => request.session[XSRF_KEY],
|
||||
CURRENT_URI_KEY => redirect_to)
|
||||
CURRENT_URI_KEY => redirect_to
|
||||
)
|
||||
options[:base_url] = request.url
|
||||
super(options)
|
||||
end
|
||||
@@ -193,7 +197,8 @@ module Google
|
||||
user_id: user_id,
|
||||
code: callback_state[AUTH_CODE_KEY],
|
||||
scope: callback_state[SCOPE_KEY],
|
||||
base_url: request.url)
|
||||
base_url: request.url
|
||||
)
|
||||
else
|
||||
super(user_id, scope)
|
||||
end
|
||||
@@ -204,7 +209,7 @@ module Google
|
||||
redirect_uri = state[CURRENT_URI_KEY]
|
||||
callback_state = {
|
||||
AUTH_CODE_KEY => request[AUTH_CODE_KEY],
|
||||
ERROR_CODE_KEY => request[ERROR_CODE_KEY],
|
||||
ERROR_CODE_KEY => request[ERROR_CODE_KEY],
|
||||
SESSION_ID_KEY => state[SESSION_ID_KEY],
|
||||
SCOPE_KEY => request[SCOPE_KEY]
|
||||
}
|
||||
@@ -223,12 +228,12 @@ module Google
|
||||
# Current request
|
||||
def self.validate_callback_state(state, request)
|
||||
if state[AUTH_CODE_KEY].nil?
|
||||
fail Signet::AuthorizationError, MISSING_AUTH_CODE_ERROR
|
||||
raise Signet::AuthorizationError, MISSING_AUTH_CODE_ERROR
|
||||
elsif state[ERROR_CODE_KEY]
|
||||
fail Signet::AuthorizationError,
|
||||
sprintf(AUTHORIZATION_ERROR, state[ERROR_CODE_KEY])
|
||||
raise Signet::AuthorizationError,
|
||||
sprintf(AUTHORIZATION_ERROR, state[ERROR_CODE_KEY])
|
||||
elsif request.session[XSRF_KEY] != state[SESSION_ID_KEY]
|
||||
fail Signet::AuthorizationError, INVALID_STATE_TOKEN_ERROR
|
||||
raise Signet::AuthorizationError, INVALID_STATE_TOKEN_ERROR
|
||||
end
|
||||
end
|
||||
|
||||
@@ -254,7 +259,7 @@ module Google
|
||||
#
|
||||
# @see {Google::Auth::WebUserAuthorizer}
|
||||
class CallbackApp
|
||||
LOCATION_HEADER = 'Location'
|
||||
LOCATION_HEADER = 'Location'.freeze
|
||||
REDIR_STATUS = 302
|
||||
ERROR_STATUS = 500
|
||||
|
||||
|
||||
Reference in new issue
Block a user