Package oauth2client :: Module tools
[hide private]
[frames] | no frames]

Source Code for Module oauth2client.tools

  1  # Copyright 2014 Google Inc. All rights reserved. 
  2  # 
  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 
  6  # 
  7  #      http://www.apache.org/licenses/LICENSE-2.0 
  8  # 
  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. 
 14   
 15  """Command-line tools for authenticating via OAuth 2.0 
 16   
 17  Do the OAuth 2.0 Web Server dance for a command line application. Stores the 
 18  generated credentials in a common file that is used by other example apps in 
 19  the same directory. 
 20  """ 
 21   
 22  __author__ = 'jcgregorio@google.com (Joe Gregorio)' 
 23  __all__ = ['argparser', 'run_flow', 'run', 'message_if_missing'] 
 24   
 25   
 26  import argparse 
 27  import BaseHTTPServer 
 28  import logging 
 29  import socket 
 30  import sys 
 31  import urlparse 
 32  import webbrowser 
 33   
 34  from oauth2client import client 
 35  from oauth2client import util 
 36   
 37  _CLIENT_SECRETS_MESSAGE = """WARNING: Please configure OAuth 2.0 
 38   
 39  To make this sample run you will need to populate the client_secrets.json file 
 40  found at: 
 41   
 42     %s 
 43   
 44  with information from the APIs Console <https://code.google.com/apis/console>. 
 45   
 46  """ 
 47   
 48  # argparser is an ArgumentParser that contains command-line options expected 
 49  # by tools.run(). Pass it in as part of the 'parents' argument to your own 
 50  # ArgumentParser. 
 51  argparser = argparse.ArgumentParser(add_help=False) 
 52  argparser.add_argument('--auth_host_name', default='localhost', 
 53                         help='Hostname when running a local web server.') 
 54  argparser.add_argument('--noauth_local_webserver', action='store_true', 
 55                         default=False, help='Do not run a local web server.') 
 56  argparser.add_argument('--auth_host_port', default=[8080, 8090], type=int, 
 57                         nargs='*', help='Port web server should listen on.') 
 58  argparser.add_argument('--logging_level', default='ERROR', 
 59                         choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 
 60                                  'CRITICAL'], 
 61                         help='Set the logging level of detail.') 
62 63 64 -class ClientRedirectServer(BaseHTTPServer.HTTPServer):
65 """A server to handle OAuth 2.0 redirects back to localhost. 66 67 Waits for a single request and parses the query parameters 68 into query_params and then stops serving. 69 """ 70 query_params = {}
71
72 73 -class ClientRedirectHandler(BaseHTTPServer.BaseHTTPRequestHandler):
74 """A handler for OAuth 2.0 redirects back to localhost. 75 76 Waits for a single request and parses the query parameters 77 into the servers query_params and then stops serving. 78 """ 79
80 - def do_GET(self):
81 """Handle a GET request. 82 83 Parses the query parameters and prints a message 84 if the flow has completed. Note that we can't detect 85 if an error occurred. 86 """ 87 self.send_response(200) 88 self.send_header("Content-type", "text/html") 89 self.end_headers() 90 query = self.path.split('?', 1)[-1] 91 query = dict(urlparse.parse_qsl(query)) 92 self.server.query_params = query 93 self.wfile.write("<html><head><title>Authentication Status</title></head>") 94 self.wfile.write("<body><p>The authentication flow has completed.</p>") 95 self.wfile.write("</body></html>")
96
97 - def log_message(self, format, *args):
98 """Do not log messages to stdout while running as command line program."""
99
100 101 @util.positional(3) 102 -def run_flow(flow, storage, flags, http=None):
103 """Core code for a command-line application. 104 105 The run() function is called from your application and runs through all the 106 steps to obtain credentials. It takes a Flow argument and attempts to open an 107 authorization server page in the user's default web browser. The server asks 108 the user to grant your application access to the user's data. If the user 109 grants access, the run() function returns new credentials. The new credentials 110 are also stored in the Storage argument, which updates the file associated 111 with the Storage object. 112 113 It presumes it is run from a command-line application and supports the 114 following flags: 115 116 --auth_host_name: Host name to use when running a local web server 117 to handle redirects during OAuth authorization. 118 (default: 'localhost') 119 120 --auth_host_port: Port to use when running a local web server to handle 121 redirects during OAuth authorization.; 122 repeat this option to specify a list of values 123 (default: '[8080, 8090]') 124 (an integer) 125 126 --[no]auth_local_webserver: Run a local web server to handle redirects 127 during OAuth authorization. 128 (default: 'true') 129 130 The tools module defines an ArgumentParser the already contains the flag 131 definitions that run() requires. You can pass that ArgumentParser to your 132 ArgumentParser constructor: 133 134 parser = argparse.ArgumentParser(description=__doc__, 135 formatter_class=argparse.RawDescriptionHelpFormatter, 136 parents=[tools.argparser]) 137 flags = parser.parse_args(argv) 138 139 Args: 140 flow: Flow, an OAuth 2.0 Flow to step through. 141 storage: Storage, a Storage to store the credential in. 142 flags: argparse.ArgumentParser, the command-line flags. 143 http: An instance of httplib2.Http.request 144 or something that acts like it. 145 146 Returns: 147 Credentials, the obtained credential. 148 """ 149 logging.getLogger().setLevel(getattr(logging, flags.logging_level)) 150 if not flags.noauth_local_webserver: 151 success = False 152 port_number = 0 153 for port in flags.auth_host_port: 154 port_number = port 155 try: 156 httpd = ClientRedirectServer((flags.auth_host_name, port), 157 ClientRedirectHandler) 158 except socket.error as e: 159 pass 160 else: 161 success = True 162 break 163 flags.noauth_local_webserver = not success 164 if not success: 165 print 'Failed to start a local webserver listening on either port 8080' 166 print 'or port 9090. Please check your firewall settings and locally' 167 print 'running programs that may be blocking or using those ports.' 168 print 169 print 'Falling back to --noauth_local_webserver and continuing with', 170 print 'authorization.' 171 print 172 173 if not flags.noauth_local_webserver: 174 oauth_callback = 'http://%s:%s/' % (flags.auth_host_name, port_number) 175 else: 176 oauth_callback = client.OOB_CALLBACK_URN 177 flow.redirect_uri = oauth_callback 178 authorize_url = flow.step1_get_authorize_url() 179 180 if not flags.noauth_local_webserver: 181 webbrowser.open(authorize_url, new=1, autoraise=True) 182 print 'Your browser has been opened to visit:' 183 print 184 print ' ' + authorize_url 185 print 186 print 'If your browser is on a different machine then exit and re-run this' 187 print 'application with the command-line parameter ' 188 print 189 print ' --noauth_local_webserver' 190 print 191 else: 192 print 'Go to the following link in your browser:' 193 print 194 print ' ' + authorize_url 195 print 196 197 code = None 198 if not flags.noauth_local_webserver: 199 httpd.handle_request() 200 if 'error' in httpd.query_params: 201 sys.exit('Authentication request was rejected.') 202 if 'code' in httpd.query_params: 203 code = httpd.query_params['code'] 204 else: 205 print 'Failed to find "code" in the query parameters of the redirect.' 206 sys.exit('Try running with --noauth_local_webserver.') 207 else: 208 code = raw_input('Enter verification code: ').strip() 209 210 try: 211 credential = flow.step2_exchange(code, http=http) 212 except client.FlowExchangeError as e: 213 sys.exit('Authentication has failed: %s' % e) 214 215 storage.put(credential) 216 credential.set_store(storage) 217 print 'Authentication successful.' 218 219 return credential
220
221 222 -def message_if_missing(filename):
223 """Helpful message to display if the CLIENT_SECRETS file is missing.""" 224 225 return _CLIENT_SECRETS_MESSAGE % filename
226 227 try: 228 from oauth2client.old_run import run 229 from oauth2client.old_run import FLAGS 230 except ImportError:
231 - def run(*args, **kwargs):
232 raise NotImplementedError( 233 'The gflags library must be installed to use tools.run(). ' 234 'Please install gflags or preferrably switch to using ' 235 'tools.run_flow().')
236