1 # Copyright 2010 Google Inc.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
21 # Small helper for the sample apps for performing OAuth 2.0 flows from the command
22 # line or in any other installed app environment.
26 # client = Google::APIClient.new
27 # flow = Google::APIClient::InstalledAppFlow.new(
28 # :client_id => '691380668085.apps.googleusercontent.com',
29 # :client_secret => '...,
30 # :scope => 'https://www.googleapis.com/auth/drive'
32 # client.authorization = flow.authorize
34 class InstalledAppFlow
36 RESPONSE_BODY = <<-HTML
40 function closeWindow() {
41 window.open('', '_self', '');
44 setTimeout(closeWindow, 10);
47 <body>You may close this window.</body>
54 # @param [Hash] options The configuration parameters for the client.
55 # @option options [Fixnum] :port
56 # Port to run the embedded server on. Defaults to 9292
57 # @option options [String] :client_id
58 # A unique identifier issued to the client to identify itself to the
59 # authorization server.
60 # @option options [String] :client_secret
61 # A shared symmetric secret issued by the authorization server,
62 # which is used to authenticate the client.
63 # @option options [String] :scope
64 # The scope of the access request, expressed either as an Array
65 # or as a space-delimited String.
67 # @see Signet::OAuth2::Client
68 def initialize(options)
69 @port = options[:port] || 9292
70 @authorization = Signet::OAuth2::Client.new({
71 :authorization_uri => 'https://accounts.google.com/o/oauth2/auth',
72 :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
73 :redirect_uri => "http://localhost:#{@port}/"}.update(options)
78 # Request authorization. Opens a browser and waits for response.
80 # @param [Google::APIClient::FileStorage] storage
81 # Optional object that responds to :write_credentials, used to serialize
82 # the OAuth 2 credentials after completing the flow.
84 # @return [Signet::OAuth2::Client]
85 # Authorization instance, nil if user cancelled.
86 def authorize(storage=nil)
89 server = WEBrick::HTTPServer.new(
91 :BindAddress =>"localhost",
92 :Logger => WEBrick::Log.new(STDOUT, 0),
95 trap("INT") { server.shutdown }
97 server.mount_proc '/' do |req, res|
98 auth.code = req.query['code']
100 auth.fetch_access_token!
102 res.status = WEBrick::HTTPStatus::RC_ACCEPTED
103 res.body = RESPONSE_BODY
107 Launchy.open(auth.authorization_uri.to_s)
109 if @authorization.access_token
110 if storage.respond_to?(:write_credentials)
111 storage.write_credentials(@authorization)
113 return @authorization