127 lines
4.0 KiB
Ruby
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
|
|
|