Added Google::APIClient::FileStorage, to save OAuth 2 credentials to disk

This is a (potentially rough) bit of code to persist OAuth 2
credentials to disk, similar to
http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.
file.Storage-class.html

It can be used in the following manner, which roughly translates to
what the Python client library code looks like.

  file_storage = Google::APIClient::FileStorage.new("#{$0}-oauth2.json")
  if file_storage.authorization.nil?
    client_secrets = Google::APIClient::ClientSecrets.load
    flow = Google::APIClient::InstalledAppFlow.new(
      :client_id => client_secrets.client_id,
      :client_secret => client_secrets.client_secret,
      :scope => [SCOPE1, SCOPE2]
    )
    client.authorization = flow.authorize(file_storage)
  else
    client.authorization = file_storage.authorization
  end
This commit is contained in:
Jeff Posnick 2013-05-29 15:31:44 -04:00
parent 9cd5601134
commit fb67a021e7
2 changed files with 95 additions and 1 deletions

View File

@ -0,0 +1,87 @@
# Copyright 2013 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'json'
require 'signet/oauth_2/client'
module Google
class APIClient
##
# Represents cached OAuth 2 tokens stored on local disk in a
# JSON serialized file. Meant to resemble the serialized format
# http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
#
class FileStorage
# @return [String] Path to the credentials file.
attr_accessor :path
# @return [Signet::OAuth2::Client] Path to the credentials file.
attr_reader :authorization
##
# Initializes the FileStorage object.
#
# @param [String] path
# Path to the credentials file.
def initialize(path)
@path = path
self.load_credentials
end
##
# Attempt to read in credentials from the specified file.
def load_credentials
if File.exist? self.path
File.open(self.path, 'r') do |file|
cached_credentials = JSON.load(file)
@authorization = Signet::OAuth2::Client.new(cached_credentials)
@authorization.issued_at = Time.at(cached_credentials['issued_at'])
if @authorization.expired?
@authorization.fetch_access_token!
self.write_credentials
end
end
end
end
##
# Write the credentials to the specified file.
#
# @param [Signet::OAuth2::Client] authorization
# Optional authorization instance. If not provided, the authorization
# already associated with this instance will be written.
def write_credentials(authorization=nil)
@authorization = authorization unless authorization.nil?
unless @authorization.refresh_token.nil?
hash = {}
%w'access_token
authorization_uri
client_id
client_secret
expires_in
refresh_token
token_credential_uri'.each do |var|
hash[var] = @authorization.instance_variable_get("@#{var}")
end
hash['issued_at'] = @authorization.issued_at.to_i
File.open(self.path, 'w', 0600) do |file|
file.write(hash.to_json)
end
end
end
end
end
end

View File

@ -77,9 +77,13 @@ module Google
##
# Request authorization. Opens a browser and waits for response.
#
# @param [Google::APIClient::FileStorage] storage
# Optional object that responds to :write_credentials, used to serialize
# the OAuth 2 credentials after completing the flow.
#
# @return [Signet::OAuth2::Client]
# Authorization instance, nil if user cancelled.
def authorize
def authorize(storage=nil)
auth = @authorization
server = WEBrick::HTTPServer.new(
@ -103,6 +107,9 @@ module Google
Launchy.open(auth.authorization_uri.to_s)
server.start
if @authorization.access_token
if storage.respond_to?(:write_credentials)
storage.write_credentials(@authorization)
end
return @authorization
else
return nil