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