def test_ClientRedirectServer(self): # create a ClientRedirectServer and run it in a thread to listen # for a mock GET request with the access token # the server should return a 200 message and store the token httpd = tools.ClientRedirectServer(('localhost', 0), tools.ClientRedirectHandler) code = 'foo' url = 'http://localhost:%i?code=%s' % (httpd.server_address[1], code) t = threading.Thread(target=httpd.handle_request) t.setDaemon(True) t.start() f = request.urlopen(url) self.assertTrue(f.read()) t.join() httpd.server_close() self.assertEqual(httpd.query_params.get('code'), code)
def __run_flow(self): success = False port_number = 0 for port in [8080, 8090]: port_number = port try: tools.ClientRedirectServer(("localhost", port), tools.ClientRedirectHandler) except socket.error: pass else: success = True break if not success: # TODO: send error print "failed_start" self.__flow.redirect_uri = client.OOB_CALLBACK_URN self.emit("login", self.__flow.step1_get_authorize_url())
def Run(flow, launch_browser=True, http=None, auth_host_name='localhost', auth_host_port_start=8085): """Run a web flow to get oauth2 credentials. Args: flow: oauth2client.OAuth2WebServerFlow, A flow that is ready to run. launch_browser: bool, If False, give the user a URL to copy into a browser. Requires that they paste the refresh token back into the terminal. If True, opens a web browser in a new window. http: httplib2.Http, The http transport to use for authentication. auth_host_name: str, Host name for the redirect server. auth_host_port_start: int, First port to try for serving the redirect. If this port is taken, it will keep trying incrementing ports until 100 have been tried, then fail. Returns: oauth2client.Credential, A ready-to-go credential that has already been put in the storage. Raises: AuthRequestRejectedException: If the request was rejected. AuthRequestFailedException: If the request fails. """ if launch_browser: # pylint:disable=g-import-not-at-top, Import when needed for performance. import socket import webbrowser success = False port_number = auth_host_port_start while True: try: httpd = tools.ClientRedirectServer( (auth_host_name, port_number), ClientRedirectHandler) except socket.error as e: if port_number > auth_host_port_start + 100: success = False break port_number += 1 else: success = True break if success: flow.redirect_uri = ('http://%s:%s/' % (auth_host_name, port_number)) authorize_url = flow.step1_get_authorize_url() # Without this, Chrome on MacOS will not launch unless Chrome # is already open. This is due to an bug in webbbrowser.py that tries to # open web browsers by app name using i.e. 'Chrome' but the actual app # name is 'Google Chrome' on Mac. if platforms.OperatingSystem.MACOSX == platforms.OperatingSystem.Current( ): try: webbrowser.register( 'Google Chrome', None, webbrowser.MacOSXOSAScript('Google Chrome'), -1) except AttributeError: # If MacOSXOSAScript not defined on module, pass # proceed with default behavior webbrowser.open(authorize_url, new=1, autoraise=True) message = 'Your browser has been opened to visit:' log.err.Print('{message}\n\n {url}\n\n'.format( message=message, url=authorize_url, )) httpd.handle_request() if 'error' in httpd.query_params: raise AuthRequestRejectedException('Unable to authenticate.') if 'code' in httpd.query_params: code = httpd.query_params['code'] else: raise AuthRequestFailedException( 'Failed to find "code" in the query parameters of the redirect.' ) else: message = ( 'Failed to start a local webserver listening on any port ' 'between {start_port} and {end_port}. Please check your ' 'firewall settings or locally running programs that may be ' 'blocking or using those ports.') log.warning( message.format( start_port=auth_host_port_start, end_port=port_number, )) launch_browser = False log.warning('Defaulting to URL copy/paste mode.') if not launch_browser: flow.redirect_uri = client.OOB_CALLBACK_URN authorize_url = flow.step1_get_authorize_url() message = 'Go to the following link in your browser:' log.err.Print('{message}\n\n {url}\n\n'.format( message=message, url=authorize_url, )) try: code = input('Enter verification code: ').strip() except EOFError as e: raise AuthRequestRejectedException(e) try: credential = flow.step2_exchange(code, http=http) except client.FlowExchangeError as e: raise AuthRequestFailedException(e) except ResponseNotReady: raise AuthRequestFailedException( 'Could not reach the login server. A potential cause of this could be ' 'because you are behind a proxy. Please set the environment variables ' 'HTTPS_PROXY and HTTP_PROXY to the address of the proxy in the format ' '"protocol://address:port" (without quotes) and try again.\n' 'Example: HTTPS_PROXY=https://192.168.0.1:8080') return credential
def Run(flow, launch_browser=True, http=None, auth_host_name='localhost', auth_host_port_start=8085): """Run a web flow to get oauth2 credentials. Args: flow: oauth2client.OAuth2WebServerFlow, A flow that is ready to run. launch_browser: bool, If False, give the user a URL to copy into a browser. Requires that they paste the refresh token back into the terminal. If True, opens a web browser in a new window. http: httplib2.Http, The http transport to use for authentication. auth_host_name: str, Host name for the redirect server. auth_host_port_start: int, First port to try for serving the redirect. If this port is taken, it will keep trying incrementing ports until 100 have been tried, then fail. Returns: oauth2client.Credential, A ready-to-go credential that has already been put in the storage. Raises: AuthRequestRejectedError: If the request was rejected. AuthRequestFailedError: If the request fails. """ if launch_browser: success = False port_number = auth_host_port_start while True: try: httpd = tools.ClientRedirectServer( (auth_host_name, port_number), ClientRedirectHandler) except socket.error as e: if port_number > auth_host_port_start + 100: success = False break port_number += 1 else: success = True break if success: flow.redirect_uri = ('http://%s:%s/' % (auth_host_name, port_number)) authorize_url = flow.step1_get_authorize_url() webbrowser.open(authorize_url, new=1, autoraise=True) message = 'Your browser has been opened to visit:' log.err.Print('{message}\n\n {url}\n\n'.format( message=message, url=authorize_url, )) httpd.handle_request() if 'error' in httpd.query_params: raise AuthRequestRejectedError('Unable to authenticate.') if 'code' in httpd.query_params: code = httpd.query_params['code'] else: raise AuthRequestFailedError( 'Failed to find "code" in the query parameters of the redirect.' ) else: message = ( 'Failed to start a local webserver listening on any port ' 'between {start_port} and {end_port}. Please check your ' 'firewall settings or locally running programs that may be ' 'blocking or using those ports.') log.warning( message.format( start_port=auth_host_port_start, end_port=port_number, )) launch_browser = False log.warning('Defaulting to URL copy/paste mode.') if not launch_browser: flow.redirect_uri = client.OOB_CALLBACK_URN authorize_url = flow.step1_get_authorize_url() message = 'Go to the following link in your browser:\n\n {url}\n\n' try: code = PromptForAuthCode(message, authorize_url) except EOFError as e: raise AuthRequestRejectedError(e) try: credential = flow.step2_exchange(code, http=http) except client.FlowExchangeError as e: raise AuthRequestFailedError(e) except ResponseNotReady as e: RaiseProxyError(e) return credential