Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
    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())
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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