def cli(obj, username):
    """Authenticate using Github, Gitlab, Google OAuth2 or Basic Auth
    username/password instead of using an API key."""
    client = obj['client']
    provider = obj['provider']
    client_id = obj['client_id']

    try:
        if provider == 'github':
            token = github.login(client, obj['github_url'], client_id)['token']
        elif provider == 'gitlab':
            token = gitlab.login(client, obj['gitlab_url'], client_id)['token']
        elif provider == 'google':
            if not username:
                username = click.prompt('Email')
            token = google.login(client, username, client_id)['token']
        elif provider == 'basic':
            if not username:
                username = click.prompt('Email')
            password = click.prompt('Password', hide_input=True)
            token = client.login(username, password)['token']
        else:
            click.echo('ERROR: unknown provider {provider}'.format(provider=provider))
            sys.exit(1)
    except Exception as e:
        raise AuthError(e)

    jwt = Jwt()
    preferred_username = jwt.parse(token)['preferred_username']
    if preferred_username:
        save_token(client.endpoint, preferred_username, token)
        click.echo('Logged in as {}'.format(preferred_username))
    else:
        click.echo('Failed to login.')
        sys.exit(1)
    def do_GET(self):
        try:
            qp = parse_qs(urlparse(self.path).query)
        except Exception as e:
            raise AuthError(e)

        if 'state' in qp and qp['state'][0] != self.xsrf_token:
            raise AuthError('CSRF token is invalid. Please try again.')
        if 'code' in qp:
            self.server.access_token = qp['code'][0]
        elif 'error' in qp:
            raise AuthError(qp['error'])

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(bytes(SUCCESS_MESSAGE.encode('utf-8')))