googleauth-0.5.1/ 0000755 0001750 0001750 00000000000 13043403213 012670 5 ustar pravi pravi googleauth-0.5.1/CHANGELOG.md 0000644 0001750 0001750 00000003561 13043403213 014506 0 ustar pravi pravi ## 0.5.1 (06/01/2016)
### Changes
* Change header name emitted by `Client#apply` from "Authorization" to "authorization" ([@murgatroid99][])
* Fix ADC not working on some windows machines ([@vsubramani][])
[#55](https://github.com/google/google-auth-library-ruby/issues/55)
## 0.5.0 (12/10/2015)
### Changes
* Initial support for user credentials ([@sqrrrl][])
* Update Signet to 0.7
## 0.4.2 (05/08/2015)
### Changes
* Updated UserRefreshCredentials hash to use string keys ([@haabaato][])
[#36](https://github.com/google/google-auth-library-ruby/issues/36)
* Add support for a system default credentials file. ([@mr-salty][])
[#33](https://github.com/google/google-auth-library-ruby/issues/33)
* Fix bug when loading credentials from ENV ([@dwilkie][])
[#31](https://github.com/google/google-auth-library-ruby/issues/31)
* Relax the constraint of dependent version of multi_json ([@igrep][])
[#30](https://github.com/google/google-auth-library-ruby/issues/30)
### Changes
* Enables passing credentials via environment variables. ([@haabaato][])
[#27](https://github.com/google/google-auth-library-ruby/issues/27)
## 0.4.1 (25/04/2015)
### Changes
* Improves handling of --no-scopes GCE authorization ([@tbetbetbe][])
* Refactoring and cleanup ([@joneslee85][])
## 0.4.0 (25/03/2015)
### Changes
* Adds an implementation of JWT header auth ([@tbetbetbe][])
## 0.3.0 (23/03/2015)
### Changes
* makes the scope parameter's optional in all APIs. ([@tbetbetbe][])
* changes the scope parameter's position in various constructors. ([@tbetbetbe][])
[@dwilkie]: https://github.com/dwilkie
[@haabaato]: https://github.com/haabaato
[@igrep]: https://github.com/igrep
[@joneslee85]: https://github.com/joneslee85
[@mr-salty]: https://github.com/mr-salty
[@tbetbetbe]: https://github.com/tbetbetbe
[@murgatroid99]: https://github.com/murgatroid99
[@vsubramani]: https://github.com/vsubramani
googleauth-0.5.1/README.md 0000644 0001750 0001750 00000013606 13043403213 014155 0 ustar pravi pravi # Google Auth Library for Ruby
- Homepage
- http://www.github.com/google/google-auth-library-ruby
- Authors
- Tim Emiola
- Copyright
- Copyright © 2015 Google, Inc.
- License
- Apache 2.0
[](http://badge.fury.io/rb/googleauth)
[](http://travis-ci.org/google/google-auth-library-ruby)
[](https://coveralls.io/r/google/google-auth-library-ruby)
[](https://gemnasium.com/google/google-auth-library-ruby)
## Description
This is Google's officially supported ruby client library for using OAuth 2.0
authorization and authentication with Google APIs.
## Alpha
This library is in Alpha. We will make an effort to support the library, but
we reserve the right to make incompatible changes when necessary.
## Install
Be sure `https://rubygems.org/` is in your gem sources.
For normal client usage, this is sufficient:
```bash
$ gem install googleauth
```
## Example Usage
```ruby
require 'googleauth'
# Get the environment configured authorization
scopes = ['https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/compute']
authorization = Google::Auth.get_application_default(scopes)
# Add the the access token obtained using the authorization to a hash, e.g
# headers.
some_headers = {}
authorization.apply(some_headers)
```
## Application Default Credentials
This library provides an implementation of
[application default credentials][application default credentials] for Ruby.
The Application Default Credentials provide a simple way to get authorization
credentials for use in calling Google APIs.
They are best suited for cases when the call needs to have the same identity
and authorization level for the application independent of the user. This is
the recommended approach to authorize calls to Cloud APIs, particularly when
you're building an application that uses Google Compute Engine.
## User Credentials
The library also provides support for requesting and storing user
credentials (3-Legged OAuth2.) Two implementations are currently available,
a generic authorizer useful for command line apps or custom integrations as
well as a web variant tailored toward Rack-based applications.
The authorizers are intended for authorization use cases. For sign-on,
see [Google Idenity Platform](https://developers.google.com/identity/)
### Example (Web)
```ruby
require 'googleauth'
require 'googleauth/web_user_authorizer'
require 'googleauth/stores/redis_token_store'
require 'redis'
client_id = Google::Auth::ClientId.from_file('/path/to/client_secrets.json')
scope = ['https://www.googleapis.com/auth/drive']
token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
authorizer = Google::Auth::WebUserAuthorizer.new(
client_id, scope, token_store, '/oauth2callback')
get('/authorize') do
# NOTE: Assumes the user is already authenticated to the app
user_id = request.session['user_id']
credentials = authorizer.get_credentials(user_id, request)
if credentials.nil?
redirect authorizer.get_authorization_url(user_id: user_id, request: request)
end
# Credentials are valid, can call APIs
# ...
end
get('/oauth2callback') do
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(
request)
redirect target_url
end
```
### Example (Command Line)
```ruby
require 'googleauth'
require 'googleauth/stores/file_token_store'
scope = 'https://www.googleapis.com/auth/drive'
client_id = Google::Auth::ClientId.from_file('/path/to/client_secrets.json')
token_store = Google::Auth::Stores::FileTokenStore.new(
:file => '/path/to/tokens.yaml')
authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store)
credentials = authorizer.get_credentials(user_id)
if credentials.nil?
url = authorizer.get_authorization_url(base_url: 'urn:ietf:wg:oauth:2.0:oob')
puts "Open #{url} in your browser and enter the resulting code:"
code = gets
credentials = authorizer.get_and_store_credentials_from_code(
user_id: user_id, code: code, base_url: OOB_URI)
end
# OK to use credentials
```
### Storage
Authorizers require a storage instance to manage long term persistence of
access and refresh tokens. Two storage implementations are included:
* Google::Auth::Stores::FileTokenStore
* Google::Auth::Stores::RedisTokenStore
Custom storage implementations can also be used. See
[token_store.rb](lib/googleauth/token_store.rb) for additional details.
## What about auth in google-apis-ruby-client?
The goal is for all auth done by
[google-apis-ruby-client][google-apis-ruby-client] to be performed by this
library. I.e, eventually google-apis-ruby-client will just take a dependency
on this library. This update is a work in progress, but should be completed
by Q2 2015.
## License
This library is licensed under Apache 2.0. Full license text is
available in [COPYING][copying].
## Contributing
See [CONTRIBUTING][contributing].
## Support
Please
[report bugs at the project on Github](https://github.com/google/google-auth-library-ruby/issues). Don't
hesitate to
[ask questions](http://stackoverflow.com/questions/tagged/google-auth-library-ruby)
about the client or APIs on [StackOverflow](http://stackoverflow.com).
[google-apis-ruby-client]: (https://github.com/google/google-api-ruby-client)
[application default credentials]: (https://developers.google.com/accounts/docs/application-default-credentials)
[contributing]: https://github.com/google/google-auth-library-ruby/tree/master/CONTRIBUTING.md
[copying]: https://github.com/google/google-auth-library-ruby/tree/master/COPYING
googleauth-0.5.1/.rubocop.yml 0000644 0001750 0001750 00000000040 13043403213 015134 0 ustar pravi pravi inherit_from: .rubocop_todo.yml
googleauth-0.5.1/googleauth.gemspec 0000755 0001750 0001750 00000002327 13043403213 016402 0 ustar pravi pravi # -*- ruby -*-
# encoding: utf-8
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
require 'googleauth/version'
Gem::Specification.new do |s|
s.name = 'googleauth'
s.version = Google::Auth::VERSION
s.authors = ['Tim Emiola']
s.email = 'temiola@google.com'
s.homepage = 'https://github.com/google/google-auth-library-ruby'
s.summary = 'Google Auth Library for Ruby'
s.license = 'Apache-2.0'
s.description = <<-eos
Allows simple authorization for accessing Google APIs.
Provide support for Application Default Credentials, as described at
https://developers.google.com/accounts/docs/application-default-credentials
eos
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- spec/*`.split("\n")
s.executables = `git ls-files -- bin/*.rb`.split("\n").map do |f|
File.basename(f)
end
s.require_paths = ['lib']
s.platform = Gem::Platform::RUBY
s.add_dependency 'faraday', '~> 0.9'
s.add_dependency 'logging', '~> 2.0'
s.add_dependency 'jwt', '~> 1.4'
s.add_dependency 'memoist', '~> 0.12'
s.add_dependency 'multi_json', '~> 1.11'
s.add_dependency 'os', '~> 0.9'
s.add_dependency 'signet', '~> 0.7'
end
googleauth-0.5.1/lib/ 0000755 0001750 0001750 00000000000 13043403213 013436 5 ustar pravi pravi googleauth-0.5.1/lib/googleauth/ 0000755 0001750 0001750 00000000000 13043403213 015574 5 ustar pravi pravi googleauth-0.5.1/lib/googleauth/user_refresh.rb 0000644 0001750 0001750 00000011355 13043403213 020622 0 ustar pravi pravi # Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'googleauth/signet'
require 'googleauth/credentials_loader'
require 'googleauth/scope_util'
require 'multi_json'
module Google
# Module Auth provides classes that provide Google-specific authorization
# used to access Google APIs.
module Auth
# Authenticates requests using User Refresh credentials.
#
# This class allows authorizing requests from user refresh tokens.
#
# This the end of the result of a 3LO flow. E.g, the end result of
# 'gcloud auth login' saves a file with these contents in well known
# location
#
# 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'
extend CredentialsLoader
# Create a UserRefreshCredentials.
#
# @param json_key_io [IO] an IO from which the JSON key can be read
# @param scope [string|array|nil] the scope(s) to access
def self.make_creds(options = {})
json_key_io, scope = options.values_at(:json_key_io, :scope)
user_creds = read_json_key(json_key_io) if json_key_io
user_creds ||= {
'client_id' => ENV[CredentialsLoader::CLIENT_ID_VAR],
'client_secret' => ENV[CredentialsLoader::CLIENT_SECRET_VAR],
'refresh_token' => ENV[CredentialsLoader::REFRESH_TOKEN_VAR]
}
new(token_credential_uri: TOKEN_CRED_URI,
client_id: user_creds['client_id'],
client_secret: user_creds['client_secret'],
refresh_token: user_creds['refresh_token'],
scope: scope)
end
# Reads the client_id, client_secret and refresh_token fields from the
# JSON key.
def self.read_json_key(json_key_io)
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)
end
json_key
end
def initialize(options = {})
options ||= {}
options[:token_credential_uri] ||= TOKEN_CRED_URI
options[:authorization_uri] ||= AUTHORIZATION_URI
super(options)
end
# Revokes the credential
def revoke!(options = {})
c = options[:connection] || Faraday.default_connection
resp = c.get(REVOKE_TOKEN_URI, token: refresh_token || access_token)
case resp.status
when 200
self.access_token = nil
self.refresh_token = nil
self.expires_at = 0
else
fail(Signet::AuthorizationError,
"Unexpected error code #{resp.status}")
end
end
# Verifies that a credential grants the requested scope
#
# @param [Array, String] required_scope
# Scope to verify
# @return [Boolean]
# True if scope is granted
def includes_scope?(required_scope)
missing_scope = Google::Auth::ScopeUtil.normalize(required_scope) -
Google::Auth::ScopeUtil.normalize(scope)
missing_scope.empty?
end
end
end
end
googleauth-0.5.1/lib/googleauth/token_store.rb 0000644 0001750 0001750 00000005005 13043403213 020455 0 ustar pravi pravi # Copyright 2014, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Google
module Auth
# Interface definition for token stores. It is not required that
# implementations inherit from this class. It is provided for documentation
# purposes to illustrate the API contract.
class TokenStore
class << self
attr_accessor :default
end
# Load the token data from storage for the given ID.
#
# @param [String] id
# ID of token data to load.
# @return [String]
# The loaded token data.
def load(_id)
fail 'Not implemented'
end
# Put the token data into storage for the given ID.
#
# @param [String] id
# ID of token data to store.
# @param [String] token
# The token data to store.
def store(_id, _token)
fail 'Not implemented'
end
# Remove the token data from storage for the given ID.
#
# @param [String] id
# ID of the token data to delete
def delete(_id)
fail 'Not implemented'
end
end
end
end
googleauth-0.5.1/lib/googleauth/compute_engine.rb 0000644 0001750 0001750 00000010507 13043403213 021125 0 ustar pravi pravi # Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'faraday'
require 'googleauth/signet'
require 'memoist'
module Google
# Module Auth provides classes that provide Google-specific authorization
# used to access Google APIs.
module Auth
NO_METADATA_SERVER_ERROR = < 'Google' }
resp = c.get(COMPUTE_AUTH_TOKEN_URI)
case resp.status
when 200
Signet::OAuth2.parse_credentials(resp.body,
resp.headers['content-type'])
when 404
fail(Signet::AuthorizationError, NO_METADATA_SERVER_ERROR)
else
msg = "Unexpected error code #{resp.status}" + UNEXPECTED_ERROR_SUFFIX
fail(Signet::AuthorizationError, msg)
end
end
end
end
end
googleauth-0.5.1/lib/googleauth/iam.rb 0000644 0001750 0001750 00000005344 13043403213 016675 0 ustar pravi pravi # Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'googleauth/signet'
require 'googleauth/credentials_loader'
require 'multi_json'
module Google
# Module Auth provides classes that provide Google-specific authorization
# used to access Google APIs.
module Auth
# Authenticates requests using IAM credentials.
class IAMCredentials
SELECTOR_KEY = 'x-goog-iam-authority-selector'
TOKEN_KEY = 'x-goog-iam-authorization-token'
# 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
@selector = selector
@token = token
end
# Adds the credential fields to the hash.
def apply!(a_hash)
a_hash[SELECTOR_KEY] = @selector
a_hash[TOKEN_KEY] = @token
a_hash
end
# Returns a clone of a_hash updated with the authoriation header
def apply(a_hash)
a_copy = a_hash.clone
apply!(a_copy)
a_copy
end
# Returns a reference to the #apply method, suitable for passing as
# a closure
def updater_proc
lambda(&method(:apply))
end
end
end
end
googleauth-0.5.1/lib/googleauth/signet.rb 0000644 0001750 0001750 00000006011 13043403213 017410 0 ustar pravi pravi # Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'signet/oauth_2/client'
module Signet
# OAuth2 supports OAuth2 authentication.
module OAuth2
AUTH_METADATA_KEY = :authorization
# Signet::OAuth2::Client creates an OAuth2 client
#
# This reopens Client to add #apply and #apply! methods which update a
# hash with the fetched authentication token.
class Client
# Updates a_hash updated with the authentication token
def apply!(a_hash, opts = {})
# fetch the access token there is currently not one, or if the client
# has expired
fetch_access_token!(opts) if access_token.nil? || expires_within?(60)
a_hash[AUTH_METADATA_KEY] = "Bearer #{access_token}"
end
# Returns a clone of a_hash updated with the authentication token
def apply(a_hash, opts = {})
a_copy = a_hash.clone
apply!(a_copy, opts)
a_copy
end
# Returns a reference to the #apply method, suitable for passing as
# a closure
def updater_proc
lambda(&method(:apply))
end
def on_refresh(&block)
@refresh_listeners ||= []
@refresh_listeners << block
end
alias_method :orig_fetch_access_token!, :fetch_access_token!
def fetch_access_token!(options = {})
info = orig_fetch_access_token!(options)
notify_refresh_listeners
info
end
def notify_refresh_listeners
listeners = @refresh_listeners || []
listeners.each do |block|
block.call(self)
end
end
end
end
end
googleauth-0.5.1/lib/googleauth/user_authorizer.rb 0000644 0001750 0001750 00000025350 13043403213 021360 0 ustar pravi pravi # Copyright 2014, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'uri'
require 'multi_json'
require 'googleauth/signet'
require 'googleauth/user_refresh'
module Google
module Auth
# Handles an interactive 3-Legged-OAuth2 (3LO) user consent authorization.
#
# Example usage for a simple command line app:
#
# credentials = authorizer.get_credentials(user_id)
# if credentials.nil?
# url = authorizer.get_authorization_url(
# base_url: OOB_URI)
# puts "Open the following URL in the browser and enter the " +
# "resulting code after authorization"
# puts url
# code = gets
# credentials = authorizer.get_and_store_credentials_from_code(
# user_id: user_id, code: code, base_url: OOB_URI)
# end
# # Credentials ready to use, call APIs
# ...
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'
MISSING_ABSOLUTE_URL_ERROR =
'Absolute base url required for relative callback url "%s"'
# Initialize the authorizer
#
# @param [Google::Auth::ClientID] client_id
# Configured ID & secret for this application
# @param [String, Array] scope
# Authorization scope to request
# @param [Google::Auth::Stores::TokenStore] token_store
# Backing storage for persisting user credentials
# @param [String] callback_uri
# 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?
@client_id = client_id
@scope = Array(scope)
@token_store = token_store
@callback_uri = callback_uri || '/oauth2callback'
end
# Build the URL for requesting authorization.
#
# @param [String] login_hint
# Login hint if need to authorize a specific account. Should be a
# user's email address or unique profile ID.
# @param [String] state
# Opaque state value to be returned to the oauth callback.
# @param [String] base_url
# Absolute URL to resolve the configured callback uri against. Required
# if the configured callback uri is a relative.
# @param [String, Array] scope
# Authorization scope to request. Overrides the instance scopes if not
# nil.
# @return [String]
# Authorization url
def get_authorization_url(options = {})
scope = options[:scope] || @scope
credentials = UserRefreshCredentials.new(
client_id: @client_id.id,
client_secret: @client_id.secret,
scope: scope)
redirect_uri = redirect_uri_for(options[:base_url])
url = credentials.authorization_uri(access_type: 'offline',
redirect_uri: redirect_uri,
approval_prompt: 'force',
state: options[:state],
include_granted_scopes: true,
login_hint: options[:login_hint])
url.to_s
end
# Fetch stored credentials for the user.
#
# @param [String] user_id
# Unique ID of the user for loading/storing credentials.
# @param [Array, String] scope
# If specified, only returns credentials that have all
# the requested scopes
# @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?
scope ||= @scope
saved_token = @token_store.load(user_id)
return nil if saved_token.nil?
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)
end
credentials = UserRefreshCredentials.new(
client_id: @client_id.id,
client_secret: @client_id.secret,
scope: data['scope'] || @scope,
access_token: data['access_token'],
refresh_token: data['refresh_token'],
expires_at: data.fetch('expiration_time_millis', 0) / 1000)
if credentials.includes_scope?(scope)
monitor_credentials(user_id, credentials)
return credentials
end
nil
end
# Exchanges an authorization code returned in the oauth callback
#
# @param [String] user_id
# Unique ID of the user for loading/storing credentials.
# @param [String] code
# The authorization code from the OAuth callback
# @param [String, Array] scope
# Authorization scope requested. Overrides the instance
# scopes if not nil.
# @param [String] base_url
# Absolute URL to resolve the configured callback uri against.
# Required if the configured
# callback uri is a relative.
# @return [Google::Auth::UserRefreshCredentials]
# Credentials if exchange is successful
def get_credentials_from_code(options = {})
user_id = options[:user_id]
code = options[:code]
scope = options[:scope] || @scope
base_url = options[:base_url]
credentials = UserRefreshCredentials.new(
client_id: @client_id.id,
client_secret: @client_id.secret,
redirect_uri: redirect_uri_for(base_url),
scope: scope)
credentials.code = code
credentials.fetch_access_token!({})
monitor_credentials(user_id, credentials)
end
# Exchanges an authorization code returned in the oauth callback.
# Additionally, stores the resulting credentials in the token store if
# the exchange is successful.
#
# @param [String] user_id
# Unique ID of the user for loading/storing credentials.
# @param [String] code
# The authorization code from the OAuth callback
# @param [String, Array] scope
# Authorization scope requested. Overrides the instance
# scopes if not nil.
# @param [String] base_url
# Absolute URL to resolve the configured callback uri against.
# Required if the configured
# callback uri is a relative.
# @return [Google::Auth::UserRefreshCredentials]
# Credentials if exchange is successful
def get_and_store_credentials_from_code(options = {})
credentials = get_credentials_from_code(options)
monitor_credentials(options[:user_id], credentials)
store_credentials(options[:user_id], credentials)
end
# Revokes a user's credentials. This both revokes the actual
# grant as well as removes the token from the token store.
#
# @param [String] user_id
# Unique ID of the user for loading/storing credentials.
def revoke_authorization(user_id)
credentials = get_credentials(user_id)
if credentials
begin
@token_store.delete(user_id)
ensure
credentials.revoke!
end
end
nil
end
# Store credentials for a user. Generally not required to be
# called directly, but may be used to migrate tokens from one
# store to another.
#
# @param [String] user_id
# Unique ID of the user for loading/storing credentials.
# @param [Google::Auth::UserRefreshCredentials] credentials
# Credentials to store.
def store_credentials(user_id, credentials)
json = MultiJson.dump(
client_id: credentials.client_id,
access_token: credentials.access_token,
refresh_token: credentials.refresh_token,
scope: credentials.scope,
expiration_time_millis: (credentials.expires_at.to_i) * 1000)
@token_store.store(user_id, json)
credentials
end
private
# Begin watching a credential for refreshes so the access token can be
# saved.
#
# @param [String] user_id
# Unique ID of the user for loading/storing credentials.
# @param [Google::Auth::UserRefreshCredentials] credentials
# Credentials to store.
def monitor_credentials(user_id, credentials)
credentials.on_refresh do |cred|
store_credentials(user_id, cred)
end
credentials
end
# Resolve the redirect uri against a base.
#
# @param [String] base_url
# Absolute URL to resolve the callback against if necessary.
# @return [String]
# Redirect URI
def redirect_uri_for(base_url)
return @callback_uri unless URI(@callback_uri).scheme.nil?
fail sprintf(
MISSING_ABSOLUTE_URL_ERROR,
@callback_uri) if base_url.nil? || URI(base_url).scheme.nil?
URI.join(base_url, @callback_uri).to_s
end
end
end
end
googleauth-0.5.1/lib/googleauth/client_id.rb 0000644 0001750 0001750 00000007255 13043403213 020064 0 ustar pravi pravi # Copyright 2014, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'multi_json'
module Google
module Auth
# 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'
MISSING_TOP_LEVEL_ELEMENT_ERROR =
"Expected top level property 'installed' or 'web' to be present."
# Text identifier of the client ID
# @return [String]
attr_reader :id
# Secret associated with the client ID
# @return [String]
attr_reader :secret
class << self
attr_accessor :default
end
# Initialize the Client ID
#
# @param [String] id
# Text identifier of the client ID
# @param [String] secret
# Secret associated with the client ID
# @note Direction instantion is discouraged to avoid embedding IDs
# & 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?
@id = id
@secret = secret
end
# Constructs a Client ID from a JSON file downloaed from the
# Google Developers Console.
#
# @param [String, File] file
# Path of file to read from
# @return [Google::Auth::ClientID]
def self.from_file(file)
fail 'File can not be nil.' if file.nil?
File.open(file.to_s) do |f|
json = f.read
config = MultiJson.load(json)
from_hash(config)
end
end
# Constructs a Client ID from a previously loaded JSON file. The hash
# structure should
# match the expected JSON format.
#
# @param [hash] config
# Parsed contents of the JSON file
# @return [Google::Auth::ClientID]
def self.from_hash(config)
fail '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?
ClientId.new(raw_detail[CLIENT_ID], raw_detail[CLIENT_SECRET])
end
end
end
end
googleauth-0.5.1/lib/googleauth/web_user_authorizer.rb 0000644 0001750 0001750 00000026043 13043403213 022215 0 ustar pravi pravi # Copyright 2014, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'multi_json'
require 'googleauth/signet'
require 'googleauth/user_authorizer'
require 'googleauth/user_refresh'
require 'securerandom'
module Google
module Auth
# Varation on {Google::Auth::UserAuthorizer} adapted for Rack based
# web applications.
#
# Example usage:
#
# get('/') do
# user_id = request.session['user_email']
# credentials = authorizer.get_credentials(user_id, request)
# if credentials.nil?
# redirect authorizer.get_authorization_url(user_id: user_id,
# request: request)
# end
# # Credentials are valid, can call APIs
# ...
# end
#
# get('/oauth2callback') do
# url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(
# request)
# redirect url
# end
#
# Instead of implementing the callback directly, applications are
# encouraged to use {Google::Auth::Web::AuthCallbackApp} instead.
#
# For rails apps, see {Google::Auth::ControllerHelpers}
#
# @see {Google::Auth::AuthCallbackApp}
# @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'
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'
class << self
attr_accessor :default
end
# Handle the result of the oauth callback. This version defers the
# exchange of the code by temporarily stashing the results in the user's
# session. This allows apps to use the generic
# {Google::Auth::WebUserAuthorizer::CallbackApp} handler for the callback
# without any additional customization.
#
# Apps that wish to handle the callback directly should use
# {#handle_auth_callback} instead.
#
# @param [Rack::Request] request
# Current request
def self.handle_auth_callback_deferred(request)
callback_state, redirect_uri = extract_callback_state(request)
request.session[CALLBACK_STATE_KEY] = MultiJson.dump(callback_state)
redirect_uri
end
# Initialize the authorizer
#
# @param [Google::Auth::ClientID] client_id
# Configured ID & secret for this application
# @param [String, Array] scope
# Authorization scope to request
# @param [Google::Auth::Stores::TokenStore] token_store
# Backing storage for persisting user credentials
# @param [String] callback_uri
# URL (either absolute or relative) of the auth callback. Defaults
# to '/oauth2callback'
def initialize(client_id, scope, token_store, callback_uri = nil)
super(client_id, scope, token_store, callback_uri)
end
# Handle the result of the oauth callback. Exchanges the authorization
# code from the request and persists to storage.
#
# @param [String] user_id
# Unique ID of the user for loading/storing credentials.
# @param [Rack::Request] request
# Current request
# @return (Google::Auth::UserRefreshCredentials, String)
# credentials & next URL to redirect to
def handle_auth_callback(user_id, request)
callback_state, redirect_uri = WebUserAuthorizer.extract_callback_state(
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)
[credentials, redirect_uri]
end
# Build the URL for requesting authorization.
#
# @param [String] login_hint
# Login hint if need to authorize a specific account. Should be a
# user's email address or unique profile ID.
# @param [Rack::Request] request
# Current request
# @param [String] redirect_to
# Optional URL to proceed to after authorization complete. Defaults to
# the current URL.
# @param [String, Array] scope
# Authorization scope to request. Overrides the instance scopes if
# not nil.
# @return [String]
# Authorization url
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?
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)
options[:base_url] = request.url
super(options)
end
# Fetch stored credentials for the user.
#
# @param [String] user_id
# Unique ID of the user for loading/storing credentials.
# @param [Rack::Request] request
# Current request
# @param [Array, String] scope
# If specified, only returns credentials that have all the \
# requested scopes
# @return [Google::Auth::UserRefreshCredentials]
# Stored credentials, nil if none present
# @raise [Signet::AuthorizationError]
# May raise an error if an authorization code is present in the session
# and exchange of the code fails
def get_credentials(user_id, request, scope = nil)
if request.session.key?(CALLBACK_STATE_KEY)
# Note - in theory, no need to check required scope as this is
# expected to be called immediately after a return from authorization
state_json = request.session.delete(CALLBACK_STATE_KEY)
callback_state = MultiJson.load(state_json)
WebUserAuthorizer.validate_callback_state(callback_state, request)
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)
else
super(user_id, scope)
end
end
def self.extract_callback_state(request)
state = MultiJson.load(request[STATE_PARAM] || '{}')
redirect_uri = state[CURRENT_URI_KEY]
callback_state = {
AUTH_CODE_KEY => request[AUTH_CODE_KEY],
ERROR_CODE_KEY => request[ERROR_CODE_KEY],
SESSION_ID_KEY => state[SESSION_ID_KEY],
SCOPE_KEY => request[SCOPE_KEY]
}
[callback_state, redirect_uri]
end
# Verifies the results of an authorization callback
#
# @param [Hash] state
# Callback state
# @option state [String] AUTH_CODE_KEY
# The authorization code
# @option state [String] ERROR_CODE_KEY
# Error message if failed
# @param [Rack::Request] request
# Current request
def self.validate_callback_state(state, request)
if state[AUTH_CODE_KEY].nil?
fail Signet::AuthorizationError, MISSING_AUTH_CODE_ERROR
elsif state[ERROR_CODE_KEY]
fail 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
end
end
# Small Rack app which acts as the default callback handler for the app.
#
# To configure in Rails, add to routes.rb:
#
# match '/oauth2callback',
# to: Google::Auth::WebUserAuthorizer::CallbackApp,
# via: :all
#
# With Rackup, add to config.ru:
#
# map '/oauth2callback' do
# run Google::Auth::WebUserAuthorizer::CallbackApp
# end
#
# Or in a classic Sinatra app:
#
# get('/oauth2callback') do
# Google::Auth::WebUserAuthorizer::CallbackApp.call(env)
# end
#
# @see {Google::Auth::WebUserAuthorizer}
class CallbackApp
LOCATION_HEADER = 'Location'
REDIR_STATUS = 302
ERROR_STATUS = 500
# Handle a rack request. Simply stores the results the authorization
# in the session temporarily and redirects back to to the previously
# saved redirect URL. Credentials can be later retrieved by calling.
# {Google::Auth::Web::WebUserAuthorizer#get_credentials}
#
# See {Google::Auth::Web::WebUserAuthorizer#get_authorization_uri}
# for how to initiate authorization requests.
#
# @param [Hash] env
# Rack environment
# @return [Array]
# HTTP response
def self.call(env)
request = Rack::Request.new(env)
return_url = WebUserAuthorizer.handle_auth_callback_deferred(request)
if return_url
[REDIR_STATUS, { LOCATION_HEADER => return_url }, []]
else
[ERROR_STATUS, {}, ['No return URL is present in the request.']]
end
end
def call(env)
self.class.call(env)
end
end
end
end
end
googleauth-0.5.1/lib/googleauth/credentials_loader.rb 0000644 0001750 0001750 00000011734 13043403213 021752 0 ustar pravi pravi # Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'memoist'
require 'os'
require 'rbconfig'
module Google
# Module Auth provides classes that provide Google-specific authorization
# used to access Google APIs.
module Auth
# CredentialsLoader contains the behaviour used to locate and find default
# credentials files on the file system.
module CredentialsLoader
extend Memoist
ENV_VAR = 'GOOGLE_APPLICATION_CREDENTIALS'
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'
CREDENTIALS_FILE_NAME = 'application_default_credentials.json'
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'
SYSTEM_DEFAULT_ERROR = 'Unable to read the system default credential file'
# make_creds proxies the construction of a credentials instance
#
# By default, it calls #new on the current class, but this behaviour can
# be modified, allowing different instances to be created.
def make_creds(*args)
new(*args)
end
# Creates an instance from the path specified in an environment
# variable.
#
# @param scope [string|array|nil] the scope(s) to access
def from_env(scope = nil)
if ENV.key?(ENV_VAR)
path = ENV[ENV_VAR]
fail "file #{path} does not exist" unless File.exist?(path)
File.open(path) do |f|
return make_creds(json_key_io: f, scope: scope)
end
elsif service_account_env_vars? || authorized_user_env_vars?
return make_creds(scope: scope)
end
rescue StandardError => e
raise "#{NOT_FOUND_ERROR}: #{e}"
end
# Creates an instance from a well known path.
#
# @param scope [string|array|nil] the scope(s) to access
def from_well_known_path(scope = nil)
home_var = OS.windows? ? 'APPDATA' : 'HOME'
base = WELL_KNOWN_PATH
root = ENV[home_var].nil? ? '' : ENV[home_var]
base = File.join('.config', base) unless OS.windows?
path = File.join(root, base)
return nil unless File.exist?(path)
File.open(path) do |f|
return make_creds(json_key_io: f, scope: scope)
end
rescue StandardError => e
raise "#{WELL_KNOWN_ERROR}: #{e}"
end
# Creates an instance from the system default path
#
# @param scope [string|array|nil] the scope(s) to access
def from_system_default_path(scope = nil)
if OS.windows?
return nil unless ENV['ProgramData']
prefix = File.join(ENV['ProgramData'], 'Google/Auth')
else
prefix = '/etc/google/auth/'
end
path = File.join(prefix, CREDENTIALS_FILE_NAME)
return nil unless File.exist?(path)
File.open(path) do |f|
return make_creds(json_key_io: f, scope: scope)
end
rescue StandardError => e
raise "#{SYSTEM_DEFAULT_ERROR}: #{e}"
end
private
def service_account_env_vars?
([PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR] - ENV.keys).empty?
end
def authorized_user_env_vars?
([CLIENT_ID_VAR, CLIENT_SECRET_VAR, REFRESH_TOKEN_VAR] -
ENV.keys).empty?
end
end
end
end
googleauth-0.5.1/lib/googleauth/stores/ 0000755 0001750 0001750 00000000000 13043403213 017113 5 ustar pravi pravi googleauth-0.5.1/lib/googleauth/stores/file_token_store.rb 0000644 0001750 0001750 00000004637 13043403213 023005 0 ustar pravi pravi # Copyright 2014, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'yaml/store'
require 'googleauth/token_store'
module Google
module Auth
module Stores
# Implementation of user token storage backed by a local YAML file
class FileTokenStore < Google::Auth::TokenStore
# Create a new store with the supplied file.
#
# @param [String, File] file
# Path to storage file
def initialize(options = {})
path = options[:file]
@store = YAML::Store.new(path)
end
# (see Google::Auth::Stores::TokenStore#load)
def load(id)
@store.transaction { @store[id] }
end
# (see Google::Auth::Stores::TokenStore#store)
def store(id, token)
@store.transaction { @store[id] = token }
end
# (see Google::Auth::Stores::TokenStore#delete)
def delete(id)
@store.transaction { @store.delete(id) }
end
end
end
end
end
googleauth-0.5.1/lib/googleauth/stores/redis_token_store.rb 0000644 0001750 0001750 00000006435 13043403213 023172 0 ustar pravi pravi # Copyright 2014, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'redis'
require 'googleauth/token_store'
module Google
module Auth
module Stores
# Implementation of user token storage backed by Redis. Tokens
# are stored as JSON using the supplied key, prefixed with
# `g-user-token:`
class RedisTokenStore < Google::Auth::TokenStore
DEFAULT_KEY_PREFIX = 'g-user-token:'
# Create a new store with the supplied redis client.
#
# @param [::Redis, String] redis
# Initialized redis client to connect to.
# @param [String] prefix
# Prefix for keys in redis. Defaults to 'g-user-token:'
# @note If no redis instance is provided, a new one is created and
# the options passed through. You may include any other keys accepted
# by `Redis.new`
def initialize(options = {})
redis = options.delete(:redis)
prefix = options.delete(:prefix)
case redis
when Redis
@redis = redis
else
@redis = Redis.new(options)
end
@prefix = prefix || DEFAULT_KEY_PREFIX
end
# (see Google::Auth::Stores::TokenStore#load)
def load(id)
key = key_for(id)
@redis.get(key)
end
# (see Google::Auth::Stores::TokenStore#store)
def store(id, token)
key = key_for(id)
@redis.set(key, token)
end
# (see Google::Auth::Stores::TokenStore#delete)
def delete(id)
key = key_for(id)
@redis.del(key)
end
private
# Generate a redis key from a token ID
#
# @param [String] id
# ID of the token
# @return [String]
# Redis key
def key_for(id)
@prefix + id
end
end
end
end
end
googleauth-0.5.1/lib/googleauth/scope_util.rb 0000644 0001750 0001750 00000004435 13043403213 020275 0 ustar pravi pravi # Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'googleauth/signet'
require 'googleauth/credentials_loader'
require 'multi_json'
module Google
module Auth
# Small utility for normalizing scopes into canonical form
module ScopeUtil
ALIASES = {
'email' => 'https://www.googleapis.com/auth/userinfo.email',
'profile' => 'https://www.googleapis.com/auth/userinfo.profile',
'openid' => 'https://www.googleapis.com/auth/plus.me'
}
def self.normalize(scope)
list = as_array(scope)
list.map { |item| ALIASES[item] || item }
end
def self.as_array(scope)
case scope
when Array
scope
when String
scope.split(' ')
else
fail 'Invalid scope value. Must be string or array'
end
end
end
end
end
googleauth-0.5.1/lib/googleauth/service_account.rb 0000644 0001750 0001750 00000017136 13043403213 021305 0 ustar pravi pravi # Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'googleauth/signet'
require 'googleauth/credentials_loader'
require 'jwt'
require 'multi_json'
require 'stringio'
module Google
# Module Auth provides classes that provide Google-specific authorization
# used to access Google APIs.
module Auth
# Authenticates requests using Google's Service Account credentials via an
# OAuth access token.
#
# This class allows authorizing requests for service accounts directly
# from credentials from a json key file downloaded from the developer
# console (via 'Generate new Json Key').
#
# cf [Application Default Credentials](http://goo.gl/mkAHpZ)
class ServiceAccountCredentials < Signet::OAuth2::Client
TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token'
extend CredentialsLoader
# Creates a ServiceAccountCredentials.
#
# @param json_key_io [IO] an IO from which the JSON key can be read
# @param scope [string|array|nil] the scope(s) to access
def self.make_creds(options = {})
json_key_io, scope = options.values_at(:json_key_io, :scope)
if json_key_io
private_key, client_email = read_json_key(json_key_io)
else
private_key = ENV[CredentialsLoader::PRIVATE_KEY_VAR]
client_email = ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
end
new(token_credential_uri: TOKEN_CRED_URI,
audience: TOKEN_CRED_URI,
scope: scope,
issuer: client_email,
signing_key: OpenSSL::PKey::RSA.new(private_key))
end
# Reads the private key and client email fields from the service account
# 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')
[json_key['private_key'], json_key['client_email']]
end
def initialize(options = {})
super(options)
end
# Extends the base class.
#
# If scope(s) is not set, it creates a transient
# ServiceAccountJwtHeaderCredentials instance and uses that to
# authenticate instead.
def apply!(a_hash, opts = {})
# Use the base implementation if scopes are set
unless scope.nil?
super
return
end
# Use the ServiceAccountJwtHeaderCredentials using the same cred values
# if no scopes are set.
cred_json = {
private_key: @signing_key.to_s,
client_email: @issuer
}
alt_clz = ServiceAccountJwtHeaderCredentials
key_io = StringIO.new(MultiJson.dump(cred_json))
alt = alt_clz.make_creds(json_key_io: key_io)
alt.apply!(a_hash)
end
end
# Authenticates requests using Google's Service Account credentials via
# JWT Header.
#
# This class allows authorizing requests for service accounts directly
# from credentials from a json key file downloaded from the developer
# console (via 'Generate new Json Key'). It is not part of any OAuth2
# flow, rather it creates a JWT and sends that as a credential.
#
# cf [Application Default Credentials](http://goo.gl/mkAHpZ)
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'
EXPIRY = 60
extend CredentialsLoader
# make_creds proxies the construction of a credentials instance
#
# make_creds is used by the methods in CredentialsLoader.
#
# By default, it calls #new with 2 args, the second one being an
# optional scope. Here's the constructor only has one param, so
# we modify make_creds to reflect this.
def self.make_creds(*args)
new(json_key_io: args[0][:json_key_io])
end
# Reads the private key and client email fields from the service account
# 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')
[json_key['private_key'], json_key['client_email']]
end
# Initializes a ServiceAccountJwtHeaderCredentials.
#
# @param json_key_io [IO] an IO from which the JSON key can be read
def initialize(options = {})
json_key_io = options[:json_key_io]
if json_key_io
private_key, client_email = self.class.read_json_key(json_key_io)
else
private_key = ENV[CredentialsLoader::PRIVATE_KEY_VAR]
client_email = ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
end
@private_key = private_key
@issuer = client_email
@signing_key = OpenSSL::PKey::RSA.new(private_key)
end
# Construct a jwt token if the JWT_AUD_URI key is present in the input
# hash.
#
# The jwt token is used as the value of a 'Bearer '.
def apply!(a_hash, opts = {})
jwt_aud_uri = a_hash.delete(JWT_AUD_URI_KEY)
return a_hash if jwt_aud_uri.nil?
jwt_token = new_jwt_token(jwt_aud_uri, opts)
a_hash[AUTH_METADATA_KEY] = "Bearer #{jwt_token}"
a_hash
end
# Returns a clone of a_hash updated with the authoriation header
def apply(a_hash, opts = {})
a_copy = a_hash.clone
apply!(a_copy, opts)
a_copy
end
# Returns a reference to the #apply method, suitable for passing as
# a closure
def updater_proc
lambda(&method(:apply))
end
protected
# Creates a jwt uri token.
def new_jwt_token(jwt_aud_uri, options = {})
now = Time.new
skew = options[:skew] || 60
assertion = {
'iss' => @issuer,
'sub' => @issuer,
'aud' => jwt_aud_uri,
'exp' => (now + EXPIRY).to_i,
'iat' => (now - skew).to_i
}
JWT.encode(assertion, @signing_key, SIGNING_ALGORITHM)
end
end
end
end
googleauth-0.5.1/lib/googleauth/version.rb 0000644 0001750 0001750 00000003241 13043403213 017606 0 ustar pravi pravi # Copyright 2014, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Google
# Module Auth provides classes that provide Google-specific authorization
# used to access Google APIs.
module Auth
VERSION = '0.5.1'
end
end
googleauth-0.5.1/lib/googleauth.rb 0000644 0001750 0001750 00000011425 13043403213 016124 0 ustar pravi pravi # Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'multi_json'
require 'stringio'
require 'googleauth/credentials_loader'
require 'googleauth/compute_engine'
require 'googleauth/service_account'
require 'googleauth/user_refresh'
require 'googleauth/client_id'
require 'googleauth/user_authorizer'
require 'googleauth/web_user_authorizer'
module Google
# Module Auth provides classes that provide Google-specific authorization
# used to access Google APIs.
module Auth
NOT_FOUND_ERROR = <