google-api-ruby-client/lib/google/api_client/auth/installed_app.rb

127 lines
4.0 KiB
Ruby

# Copyright 2010 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 'webrick'
require 'launchy'
module Google
class APIClient
# Small helper for the sample apps for performing OAuth 2.0 flows from the command
# line or in any other installed app environment.
#
# @example
#
# client = Google::APIClient.new
# flow = Google::APIClient::InstalledAppFlow.new(
# :client_id => '691380668085.apps.googleusercontent.com',
# :client_secret => '...',
# :scope => 'https://www.googleapis.com/auth/drive'
# )
# client.authorization = flow.authorize
#
class InstalledAppFlow
RESPONSE_BODY = <<-HTML
<html>
<head>
<script>
function closeWindow() {
window.open('', '_self', '');
window.close();
}
setTimeout(closeWindow, 10);
</script>
</head>
<body>You may close this window.</body>
</html>
HTML
##
# Configure the flow
#
# @param [Hash] options The configuration parameters for the client.
# @option options [Fixnum] :port
# Port to run the embedded server on. Defaults to 9292
# @option options [String] :client_id
# A unique identifier issued to the client to identify itself to the
# authorization server.
# @option options [String] :client_secret
# A shared symmetric secret issued by the authorization server,
# which is used to authenticate the client.
# @option options [String] :scope
# The scope of the access request, expressed either as an Array
# or as a space-delimited String.
#
# @see Signet::OAuth2::Client
def initialize(options)
@port = options[:port] || 9292
@authorization = Signet::OAuth2::Client.new({
:authorization_uri => 'https://accounts.google.com/o/oauth2/auth',
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:redirect_uri => "http://localhost:#{@port}/"}.update(options)
)
end
##
# 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(storage=nil)
auth = @authorization
server = WEBrick::HTTPServer.new(
:Port => @port,
:BindAddress =>"localhost",
:Logger => WEBrick::Log.new(STDOUT, 0),
:AccessLog => []
)
begin
trap("INT") { server.shutdown }
server.mount_proc '/' do |req, res|
auth.code = req.query['code']
if auth.code
auth.fetch_access_token!
end
res.status = WEBrick::HTTPStatus::RC_ACCEPTED
res.body = RESPONSE_BODY
server.stop
end
Launchy.open(auth.authorization_uri.to_s)
server.start
ensure
server.shutdown
end
if @authorization.access_token
if storage.respond_to?(:write_credentials)
storage.write_credentials(@authorization)
end
return @authorization
else
return nil
end
end
end
end
end