# Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""An OAuth 2.0 client.

Tools for interacting with OAuth 2.0 protected resources.
"""

import base64
import collections
import copy
import datetime
import json
import logging
import os
import socket
import sys
import tempfile
import time
import shutil
import six
from six.moves import urllib

import httplib2
from oauth2client import GOOGLE_AUTH_URI
from oauth2client import GOOGLE_DEVICE_URI
from oauth2client import GOOGLE_REVOKE_URI
from oauth2client import GOOGLE_TOKEN_URI
from oauth2client import GOOGLE_TOKEN_INFO_URI
from oauth2client._helpers import _from_bytes
from oauth2client._helpers import _to_bytes
from oauth2client._helpers import _urlsafe_b64decode
from oauth2client import clientsecrets
from oauth2client import util


__author__ = 'jcgregorio@google.com (Joe Gregorio)'

HAS_OPENSSL = False
HAS_CRYPTO = False
try:
    from oauth2client import crypt
    HAS_CRYPTO = True
    if crypt.OpenSSLVerifier is not None:
        HAS_OPENSSL = True
except ImportError:
    pass


logger = logging.getLogger(__name__)

# Expiry is stored in RFC3339 UTC format
EXPIRY_FORMAT = '%Y-%m-%dT%H:%M:%SZ'

# Which certs to use to validate id_tokens received.
ID_TOKEN_VERIFICATION_CERTS = 'https://www.googleapis.com/oauth2/v1/certs'
# This symbol previously had a typo in the name; we keep the old name
# around for now, but will remove it in the future.
ID_TOKEN_VERIFICATON_CERTS = ID_TOKEN_VERIFICATION_CERTS

# Constant to use for the out of band OAuth 2.0 flow.
OOB_CALLBACK_URN = 'urn:ietf:wg:oauth:2.0:oob'

# Google Data client libraries may need to set this to [401, 403].
REFRESH_STATUS_CODES = [401]

# The value representing user credentials.
AUTHORIZED_USER = 'authorized_user'

# The value representing service account credentials.
SERVICE_ACCOUNT = 'service_account'

# The environment variable pointing the file with local
# Application Default Credentials.
GOOGLE_APPLICATION_CREDENTIALS = 'GOOGLE_APPLICATION_CREDENTIALS'
# The ~/.config subdirectory containing gcloud credentials. Intended
# to be swapped out in tests.
_CLOUDSDK_CONFIG_DIRECTORY = 'gcloud'
# The environment variable name which can replace ~/.config if set.
_CLOUDSDK_CONFIG_ENV_VAR = 'CLOUDSDK_CONFIG'

# The error message we show users when we can't find the Application
# Default Credentials.
ADC_HELP_MSG = (
    'The Application Default Credentials are not available. They are '
    'available if running in Google Compute Engine. Otherwise, the '
    'environment variable ' +
    GOOGLE_APPLICATION_CREDENTIALS +
    ' must be defined pointing to a file defining the credentials. See '
    'https://developers.google.com/accounts/docs/'
    'application-default-credentials for more information.')

# The access token along with the seconds in which it expires.
AccessTokenInfo = collections.namedtuple(
    'AccessTokenInfo', ['access_token', 'expires_in'])

DEFAULT_ENV_NAME = 'UNKNOWN'

# If set to True _get_environment avoid GCE check (_detect_gce_environment)
NO_GCE_CHECK = os.environ.setdefault('NO_GCE_CHECK', 'False')

_SERVER_SOFTWARE = 'SERVER_SOFTWARE'
_GCE_METADATA_HOST = '169.254.169.254'
_METADATA_FLAVOR_HEADER = 'Metadata-Flavor'
_DESIRED_METADATA_FLAVOR = 'Google'


class SETTINGS(object):
    """Settings namespace for globally defined values."""
    env_name = None


class Error(Exception):
    """Base error for this module."""


class FlowExchangeError(Error):
    """Error trying to exchange an authorization grant for an access token."""


class AccessTokenRefreshError(Error):
    """Error trying to refresh an expired access token."""


class HttpAccessTokenRefreshError(AccessTokenRefreshError):
    """Error (with HTTP status) trying to refresh an expired access token."""
    def __init__(self, *args, **kwargs):
        super(HttpAccessTokenRefreshError, self).__init__(*args)
        self.status = kwargs.get('status')


class TokenRevokeError(Error):
    """Error trying to revoke a token."""


class UnknownClientSecretsFlowError(Error):
    """The client secrets file called for an unknown type of OAuth 2.0 flow."""


class AccessTokenCredentialsError(Error):
    """Having only the access_token means no refresh is possible."""


class VerifyJwtTokenError(Error):
    """Could not retrieve certificates for validation."""


class NonAsciiHeaderError(Error):
    """Header names and values must be ASCII strings."""


class ApplicationDefaultCredentialsError(Error):
    """Error retrieving the Application Default Credentials."""


class OAuth2DeviceCodeError(Error):
    """Error trying to retrieve a device code."""


class CryptoUnavailableError(Error, NotImplementedError):
    """Raised when a crypto library is required, but none is available."""


def _abstract():
    raise NotImplementedError('You need to override this function')


class MemoryCache(object):
    """httplib2 Cache implementation which only caches locally."""

    def __init__(self):
        self.cache = {}

    def get(self, key):
        return self.cache.get(key)

    def set(self, key, value):
        self.cache[key] = value

    def delete(self, key):
        self.cache.pop(key, None)


class Credentials(object):
    """Base class for all Credentials objects.

    Subclasses must define an authorize() method that applies the credentials
    to an HTTP transport.

    Subclasses must also specify a classmethod named 'from_json' that takes a
    JSON string as input and returns an instantiated Credentials object.
    """

    NON_SERIALIZED_MEMBERS = ['store']

    def authorize(self, http):
        """Take an httplib2.Http instance (or equivalent) and authorizes it.

        Authorizes it for the set of credentials, usually by replacing
        http.request() with a method that adds in the appropriate headers and
        then delegates to the original Http.request() method.

        Args:
            http: httplib2.Http, an http object to be used to make the refresh
                  request.
        """
        _abstract()

    def refresh(self, http):
        """Forces a refresh of the access_token.

        Args:
            http: httplib2.Http, an http object to be used to make the refresh
                  request.
        """
        _abstract()

    def revoke(self, http):
        """Revokes a refresh_token and makes the credentials void.

        Args:
            http: httplib2.Http, an http object to be used to make the revoke
                  request.
        """
        _abstract()

    def apply(self, headers):
        """Add the authorization to the headers.

        Args:
            headers: dict, the headers to add the Authorization header to.
        """
        _abstract()

    def _to_json(self, strip):
        """Utility function that creates JSON repr. of a Credentials object.

        Args:
            strip: array, An array of names of members to not include in the
                   JSON.

        Returns:
            string, a JSON representation of this instance, suitable to pass to
            from_json().
        """
        t = type(self)
        d = copy.copy(self.__dict__)
        for member in strip:
            if member in d:
                del d[member]
        if (d.get('token_expiry') and
                isinstance(d['token_expiry'], datetime.datetime)):
            d['token_expiry'] = d['token_expiry'].strftime(EXPIRY_FORMAT)
        # Add in information we will need later to reconsistitue this instance.
        d['_class'] = t.__name__
        d['_module'] = t.__module__
        for key, val in d.items():
            if isinstance(val, bytes):
                d[key] = val.decode('utf-8')
            if isinstance(val, set):
                d[key] = list(val)
        return json.dumps(d)

    def to_json(self):
        """Creating a JSON representation of an instance of Credentials.

        Returns:
            string, a JSON representation of this instance, suitable to pass to
            from_json().
        """
        return self._to_json(Credentials.NON_SERIALIZED_MEMBERS)

    @classmethod
    def new_from_json(cls, s):
        """Utility class method to instantiate a Credentials subclass from JSON.

        Expects the JSON string to have been produced by to_json().

        Args:
            s: string or bytes, JSON from to_json().

        Returns:
            An instance of the subclass of Credentials that was serialized with
            to_json().
        """
        json_string_as_unicode = _from_bytes(s)
        data = json.loads(json_string_as_unicode)
        # Find and call the right classmethod from_json() to restore
        # the object.
        module_name = data['_module']
        try:
            module_obj = __import__(module_name)
        except ImportError:
            # In case there's an object from the old package structure,
            # update it
            module_name = module_name.replace('.googleapiclient', '')
            module_obj = __import__(module_name)

        module_obj = __import__(module_name,
                                fromlist=module_name.split('.')[:-1])
        kls = getattr(module_obj, data['_class'])
        from_json = getattr(kls, 'from_json')
        return from_json(json_string_as_unicode)

    @classmethod
    def from_json(cls, unused_data):
        """Instantiate a Credentials object from a JSON description of it.

        The JSON should have been produced by calling .to_json() on the object.

        Args:
            unused_data: dict, A deserialized JSON object.

        Returns:
            An instance of a Credentials subclass.
        """
        return Credentials()


class Flow(object):
    """Base class for all Flow objects."""
    pass


class Storage(object):
    """Base class for all Storage objects.

    Store and retrieve a single credential. This class supports locking
    such that multiple processes and threads can operate on a single
    store.
    """

    def acquire_lock(self):
        """Acquires any lock necessary to access this Storage.

        This lock is not reentrant.
        """
        pass

    def release_lock(self):
        """Release the Storage lock.

        Trying to release a lock that isn't held will result in a
        RuntimeError.
        """
        pass

    def locked_get(self):
        """Retrieve credential.

        The Storage lock must be held when this is called.

        Returns:
            oauth2client.client.Credentials
        """
        _abstract()

    def locked_put(self, credentials):
        """Write a credential.

        The Storage lock must be held when this is called.

        Args:
            credentials: Credentials, the credentials to store.
        """
        _abstract()

    def locked_delete(self):
        """Delete a credential.

        The Storage lock must be held when this is called.
        """
        _abstract()

    def get(self):
        """Retrieve credential.

        The Storage lock must *not* be held when this is called.

        Returns:
            oauth2client.client.Credentials
        """
        self.acquire_lock()
        try:
            return self.locked_get()
        finally:
            self.release_lock()

    def put(self, credentials):
        """Write a credential.

        The Storage lock must be held when this is called.

        Args:
            credentials: Credentials, the credentials to store.
        """
        self.acquire_lock()
        try:
            self.locked_put(credentials)
        finally:
            self.release_lock()

    def delete(self):
        """Delete credential.

        Frees any resources associated with storing the credential.
        The Storage lock must *not* be held when this is called.

        Returns:
            None
        """
        self.acquire_lock()
        try:
            return self.locked_delete()
        finally:
            self.release_lock()


def clean_headers(headers):
    """Forces header keys and values to be strings, i.e not unicode.

    The httplib module just concats the header keys and values in a way that
    may make the message header a unicode string, which, if it then tries to
    contatenate to a binary request body may result in a unicode decode error.

    Args:
        headers: dict, A dictionary of headers.

    Returns:
        The same dictionary but with all the keys converted to strings.
    """
    clean = {}
    try:
        for k, v in six.iteritems(headers):
            if not isinstance(k, six.binary_type):
                k = str(k)
            if not isinstance(v, six.binary_type):
                v = str(v)
            clean[_to_bytes(k)] = _to_bytes(v)
    except UnicodeEncodeError:
        raise NonAsciiHeaderError(k, ': ', v)
    return clean


def _update_query_params(uri, params):
    """Updates a URI with new query parameters.

    Args:
        uri: string, A valid URI, with potential existing query parameters.
        params: dict, A dictionary of query parameters.

    Returns:
        The same URI but with the new query parameters added.
    """
    parts = urllib.parse.urlparse(uri)
    query_params = dict(urllib.parse.parse_qsl(parts.query))
    query_params.update(params)
    new_parts = parts._replace(query=urllib.parse.urlencode(query_params))
    return urllib.parse.urlunparse(new_parts)


class OAuth2Credentials(Credentials):
    """Credentials object for OAuth 2.0.

    Credentials can be applied to an httplib2.Http object using the authorize()
    method, which then adds the OAuth 2.0 access token to each request.

    OAuth2Credentials objects may be safely pickled and unpickled.
    """

    @util.positional(8)
    def __init__(self, access_token, client_id, client_secret, refresh_token,
                 token_expiry, token_uri, user_agent, revoke_uri=None,
                 id_token=None, token_response=None, scopes=None,
                 token_info_uri=None):
        """Create an instance of OAuth2Credentials.

        This constructor is not usually called by the user, instead
        OAuth2Credentials objects are instantiated by the OAuth2WebServerFlow.

        Args:
            access_token: string, access token.
            client_id: string, client identifier.
            client_secret: string, client secret.
            refresh_token: string, refresh token.
            token_expiry: datetime, when the access_token expires.
            token_uri: string, URI of token endpoint.
            user_agent: string, The HTTP User-Agent to provide for this
                        application.
            revoke_uri: string, URI for revoke endpoint. Defaults to None; a
                        token can't be revoked if this is None.
            id_token: object, The identity of the resource owner.
            token_response: dict, the decoded response to the token request.
                            None if a token hasn't been requested yet. Stored
                            because some providers (e.g. wordpress.com) include
                            extra fields that clients may want.
            scopes: list, authorized scopes for these credentials.
          token_info_uri: string, the URI for the token info endpoint. Defaults
                          to None; scopes can not be refreshed if this is None.

        Notes:
            store: callable, A callable that when passed a Credential
                   will store the credential back to where it came from.
                   This is needed to store the latest access_token if it
                   has expired and been refreshed.
        """
        self.access_token = access_token
        self.client_id = client_id
        self.client_secret = client_secret
        self.refresh_token = refresh_token
        self.store = None
        self.token_expiry = token_expiry
        self.token_uri = token_uri
        self.user_agent = user_agent
        self.revoke_uri = revoke_uri
        self.id_token = id_token
        self.token_response = token_response
        self.scopes = set(util.string_to_scopes(scopes or []))
        self.token_info_uri = token_info_uri

        # True if the credentials have been revoked or expired and can't be
        # refreshed.
        self.invalid = False

    def authorize(self, http):
        """Authorize an httplib2.Http instance with these credentials.

        The modified http.request method will add authentication headers to
        each request and will refresh access_tokens when a 401 is received on a
        request. In addition the http.request method has a credentials
        property, http.request.credentials, which is the Credentials object
        that authorized it.

        Args:
            http: An instance of ``httplib2.Http`` or something that acts
                  like it.

        Returns:
            A modified instance of http that was passed in.

        Example::

            h = httplib2.Http()
            h = credentials.authorize(h)

        You can't create a new OAuth subclass of httplib2.Authentication
        because it never gets passed the absolute URI, which is needed for
        signing. So instead we have to overload 'request' with a closure
        that adds in the Authorization header and then calls the original
        version of 'request()'.
        """
        request_orig = http.request

        # The closure that will replace 'httplib2.Http.request'.
        def new_request(uri, method='GET', body=None, headers=None,
                        redirections=httplib2.DEFAULT_MAX_REDIRECTS,
                        connection_type=None):
            if not self.access_token:
                logger.info('Attempting refresh to obtain '
                            'initial access_token')
                self._refresh(request_orig)

            # Clone and modify the request headers to add the appropriate
            # Authorization header.
            if headers is None:
                headers = {}
            else:
                headers = dict(headers)
            self.apply(headers)

            if self.user_agent is not None:
                if 'user-agent' in headers:
                    headers['user-agent'] = (self.user_agent + ' ' +
                                             headers['user-agent'])
                else:
                    headers['user-agent'] = self.user_agent

            body_stream_position = None
            if all(getattr(body, stream_prop, None) for stream_prop in
                   ('read', 'seek', 'tell')):
                body_stream_position = body.tell()

            resp, content = request_orig(uri, method, body,
                                         clean_headers(headers),
                                         redirections, connection_type)

            # A stored token may expire between the time it is retrieved and
            # the time the request is made, so we may need to try twice.
            max_refresh_attempts = 2
            for refresh_attempt in range(max_refresh_attempts):
                if resp.status not in REFRESH_STATUS_CODES:
                    break
                logger.info(
                    'OAuth token TTL expired, auto-refreshing (attempt %s/%s)',
                    refresh_attempt + 1,
                    max_refresh_attempts)
                self._refresh(request_orig)
                self.apply(headers)
                if body_stream_position is not None:
                    body.seek(body_stream_position)

                resp, content = request_orig(uri, method, body,
                                             clean_headers(headers),
                                             redirections, connection_type)

            return (resp, content)

        # Replace the request method with our own closure.
        http.request = new_request

        # Set credentials as a property of the request method.
        setattr(http.request, 'credentials', self)

        return http

    def refresh(self, http):
        """Forces a refresh of the access_token.

        Args:
            http: httplib2.Http, an http object to be used to make the refresh
                  request.
        """
        self._refresh(http.request)

    def revoke(self, http):
        """Revokes a refresh_token and makes the credentials void.

        Args:
            http: httplib2.Http, an http object to be used to make the revoke
                  request.
        """
        self._revoke(http.request)

    def apply(self, headers):
        """Add the authorization to the headers.

        Args:
            headers: dict, the headers to add the Authorization header to.
        """
        headers['Authorization'] = 'Bearer ' + self.access_token

    def has_scopes(self, scopes):
        """Verify that the credentials are authorized for the given scopes.

        Returns True if the credentials authorized scopes contain all of the
        scopes given.

        Args:
            scopes: list or string, the scopes to check.

        Notes:
            There are cases where the credentials are unaware of which scopes
            are authorized. Notably, credentials obtained and stored before
            this code was added will not have scopes, AccessTokenCredentials do
            not have scopes. In both cases, you can use refresh_scopes() to
            obtain the canonical set of scopes.
        """
        scopes = util.string_to_scopes(scopes)
        return set(scopes).issubset(self.scopes)

    def retrieve_scopes(self, http):
        """Retrieves the canonical list of scopes for this access token.

        Gets the scopes from the OAuth2 provider.

        Args:
            http: httplib2.Http, an http object to be used to make the refresh
                  request.

        Returns:
            A set of strings containing the canonical list of scopes.
        """
        self._retrieve_scopes(http.request)
        return self.scopes

    def to_json(self):
        return self._to_json(Credentials.NON_SERIALIZED_MEMBERS)

    @classmethod
    def from_json(cls, s):
        """Instantiate a Credentials object from a JSON description of it.

        The JSON should have been produced by calling .to_json() on the object.

        Args:
            data: dict, A deserialized JSON object.

        Returns:
            An instance of a Credentials subclass.
        """
        s = _from_bytes(s)
        data = json.loads(s)
        if (data.get('token_expiry') and
                not isinstance(data['token_expiry'], datetime.datetime)):
            try:
                data['token_expiry'] = datetime.datetime.strptime(
                    data['token_expiry'], EXPIRY_FORMAT)
            except ValueError:
                data['token_expiry'] = None
        retval = cls(
            data['access_token'],
            data['client_id'],
            data['client_secret'],
            data['refresh_token'],
            data['token_expiry'],
            data['token_uri'],
            data['user_agent'],
            revoke_uri=data.get('revoke_uri', None),
            id_token=data.get('id_token', None),
            token_response=data.get('token_response', None),
            scopes=data.get('scopes', None),
            token_info_uri=data.get('token_info_uri', None))
        retval.invalid = data['invalid']
        return retval

    @property
    def access_token_expired(self):
        """True if the credential is expired or invalid.

        If the token_expiry isn't set, we assume the token doesn't expire.
        """
        if self.invalid:
            return True

        if not self.token_expiry:
            return False

        now = datetime.datetime.utcnow()
        if now >= self.token_expiry:
            logger.info('access_token is expired. Now: %s, token_expiry: %s',
                        now, self.token_expiry)
            return True
        return False

    def get_access_token(self, http=None):
        """Return the access token and its expiration information.

        If the token does not exist, get one.
        If the token expired, refresh it.
        """
        if not self.access_token or self.access_token_expired:
            if not http:
                http = httplib2.Http()
            self.refresh(http)
        return AccessTokenInfo(access_token=self.access_token,
                               expires_in=self._expires_in())

    def set_store(self, store):
        """Set the Storage for the credential.

        Args:
            store: Storage, an implementation of Storage object.
                   This is needed to store the latest access_token if it
                   has expired and been refreshed. This implementation uses
                   locking to check for updates before updating the
                   access_token.
        """
        self.store = store

    def _expires_in(self):
        """Return the number of seconds until this token expires.

        If token_expiry is in the past, this method will return 0, meaning the
        token has already expired.

        If token_expiry is None, this method will return None. Note that
        returning 0 in such a case would not be fair: the token may still be
        valid; we just don't know anything about it.
        """
        if self.token_expiry:
            now = datetime.datetime.utcnow()
            if self.token_expiry > now:
                time_delta = self.token_expiry - now
                # TODO(orestica): return time_delta.total_seconds()
                # once dropping support for Python 2.6
                return time_delta.days * 86400 + time_delta.seconds
            else:
                return 0

    def _updateFromCredential(self, other):
        """Update this Credential from another instance."""
        self.__dict__.update(other.__getstate__())

    def __getstate__(self):
        """Trim the state down to something that can be pickled."""
        d = copy.copy(self.__dict__)
        del d['store']
        return d

    def __setstate__(self, state):
        """Reconstitute the state of the object from being pickled."""
        self.__dict__.update(state)
        self.store = None

    def _generate_refresh_request_body(self):
        """Generate the body that will be used in the refresh request."""
        body = urllib.parse.urlencode({
            'grant_type': 'refresh_token',
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'refresh_token': self.refresh_token,
        })
        return body

    def _generate_refresh_request_headers(self):
        """Generate the headers that will be used in the refresh request."""
        headers = {
            'content-type': 'application/x-www-form-urlencoded',
        }

        if self.user_agent is not None:
            headers['user-agent'] = self.user_agent

        return headers

    def _refresh(self, http_request):
        """Refreshes the access_token.

        This method first checks by reading the Storage object if available.
        If a refresh is still needed, it holds the Storage lock until the
        refresh is completed.

        Args:
            http_request: callable, a callable that matches the method
                          signature of httplib2.Http.request, used to make the
                          refresh request.

        Raises:
            HttpAccessTokenRefreshError: When the refresh fails.
        """
        if not self.store:
            self._do_refresh_request(http_request)
        else:
            self.store.acquire_lock()
            try:
                new_cred = self.store.locked_get()

                if (new_cred and not new_cred.invalid and
                        new_cred.access_token != self.access_token and
                        not new_cred.access_token_expired):
                    logger.info('Updated access_token read from Storage')
                    self._updateFromCredential(new_cred)
                else:
                    self._do_refresh_request(http_request)
            finally:
                self.store.release_lock()

    def _do_refresh_request(self, http_request):
        """Refresh the access_token using the refresh_token.

        Args:
            http_request: callable, a callable that matches the method
                          signature of httplib2.Http.request, used to make the
                          refresh request.

        Raises:
            HttpAccessTokenRefreshError: When the refresh fails.
        """
        body = self._generate_refresh_request_body()
        headers = self._generate_refresh_request_headers()

        logger.info('Refreshing access_token')
        resp, content = http_request(
            self.token_uri, method='POST', body=body, headers=headers)
        content = _from_bytes(content)
        if resp.status == 200:
            d = json.loads(content)
            self.token_response = d
            self.access_token = d['access_token']
            self.refresh_token = d.get('refresh_token', self.refresh_token)
            if 'expires_in' in d:
                self.token_expiry = datetime.timedelta(
                    seconds=int(d['expires_in'])) + datetime.datetime.utcnow()
            else:
                self.token_expiry = None
            # On temporary refresh errors, the user does not actually have to
            # re-authorize, so we unflag here.
            self.invalid = False
            if self.store:
                self.store.locked_put(self)
        else:
            # An {'error':...} response body means the token is expired or
            # revoked, so we flag the credentials as such.
            logger.info('Failed to retrieve access token: %s', content)
            error_msg = 'Invalid response %s.' % resp['status']
            try:
                d = json.loads(content)
                if 'error' in d:
                    error_msg = d['error']
                    if 'error_description' in d:
                        error_msg += ': ' + d['error_description']
                    self.invalid = True
                    if self.store:
                        self.store.locked_put(self)
            except (TypeError, ValueError):
                pass
            raise HttpAccessTokenRefreshError(error_msg, status=resp.status)

    def _revoke(self, http_request):
        """Revokes this credential and deletes the stored copy (if it exists).

        Args:
            http_request: callable, a callable that matches the method
                          signature of httplib2.Http.request, used to make the
                          revoke request.
        """
        self._do_revoke(http_request, self.refresh_token or self.access_token)

    def _do_revoke(self, http_request, token):
        """Revokes this credential and deletes the stored copy (if it exists).

        Args:
            http_request: callable, a callable that matches the method
                          signature of httplib2.Http.request, used to make the
                          refresh request.
            token: A string used as the token to be revoked. Can be either an
                   access_token or refresh_token.

        Raises:
            TokenRevokeError: If the revoke request does not return with a
                              200 OK.
        """
        logger.info('Revoking token')
        query_params = {'token': token}
        token_revoke_uri = _update_query_params(self.revoke_uri, query_params)
        resp, content = http_request(token_revoke_uri)
        if resp.status == 200:
            self.invalid = True
        else:
            error_msg = 'Invalid response %s.' % resp.status
            try:
                d = json.loads(_from_bytes(content))
                if 'error' in d:
                    error_msg = d['error']
            except (TypeError, ValueError):
                pass
            raise TokenRevokeError(error_msg)

        if self.store:
            self.store.delete()

    def _retrieve_scopes(self, http_request):
        """Retrieves the list of authorized scopes from the OAuth2 provider.

        Args:
            http_request: callable, a callable that matches the method
                          signature of httplib2.Http.request, used to make the
                          revoke request.
        """
        self._do_retrieve_scopes(http_request, self.access_token)

    def _do_retrieve_scopes(self, http_request, token):
        """Retrieves the list of authorized scopes from the OAuth2 provider.

        Args:
            http_request: callable, a callable that matches the method
                          signature of httplib2.Http.request, used to make the
                          refresh request.
            token: A string used as the token to identify the credentials to
                   the provider.

        Raises:
            Error: When refresh fails, indicating the the access token is
                   invalid.
        """
        logger.info('Refreshing scopes')
        query_params = {'access_token': token, 'fields': 'scope'}
        token_info_uri = _update_query_params(self.token_info_uri,
                                              query_params)
        resp, content = http_request(token_info_uri)
        content = _from_bytes(content)
        if resp.status == 200:
            d = json.loads(content)
            self.scopes = set(util.string_to_scopes(d.get('scope', '')))
        else:
            error_msg = 'Invalid response %s.' % (resp.status,)
            try:
                d = json.loads(content)
                if 'error_description' in d:
                    error_msg = d['error_description']
            except (TypeError, ValueError):
                pass
            raise Error(error_msg)


class AccessTokenCredentials(OAuth2Credentials):
    """Credentials object for OAuth 2.0.

    Credentials can be applied to an httplib2.Http object using the
    authorize() method, which then signs each request from that object
    with the OAuth 2.0 access token. This set of credentials is for the
    use case where you have acquired an OAuth 2.0 access_token from
    another place such as a JavaScript client or another web
    application, and wish to use it from Python. Because only the
    access_token is present it can not be refreshed and will in time
    expire.

    AccessTokenCredentials objects may be safely pickled and unpickled.

    Usage::

        credentials = AccessTokenCredentials('<an access token>',
            'my-user-agent/1.0')
        http = httplib2.Http()
        http = credentials.authorize(http)

    Raises:
        AccessTokenCredentialsExpired: raised when the access_token expires or
                                       is revoked.
    """

    def __init__(self, access_token, user_agent, revoke_uri=None):
        """Create an instance of OAuth2Credentials

        This is one of the few types if Credentials that you should contrust,
        Credentials objects are usually instantiated by a Flow.

        Args:
            access_token: string, access token.
            user_agent: string, The HTTP User-Agent to provide for this
                        application.
            revoke_uri: string, URI for revoke endpoint. Defaults to None; a
                        token can't be revoked if this is None.
        """
        super(AccessTokenCredentials, self).__init__(
            access_token,
            None,
            None,
            None,
            None,
            None,
            user_agent,
            revoke_uri=revoke_uri)

    @classmethod
    def from_json(cls, s):
        data = json.loads(_from_bytes(s))
        retval = AccessTokenCredentials(
            data['access_token'],
            data['user_agent'])
        return retval

    def _refresh(self, http_request):
        raise AccessTokenCredentialsError(
            'The access_token is expired or invalid and can\'t be refreshed.')

    def _revoke(self, http_request):
        """Revokes the access_token and deletes the store if available.

        Args:
            http_request: callable, a callable that matches the method
                          signature of httplib2.Http.request, used to make the
                          revoke request.
        """
        self._do_revoke(http_request, self.access_token)


def _detect_gce_environment():
    """Determine if the current environment is Compute Engine.

    Returns:
        Boolean indicating whether or not the current environment is Google
        Compute Engine.
    """
    # NOTE: The explicit ``timeout`` is a workaround. The underlying
    #       issue is that resolving an unknown host on some networks will take
    #       20-30 seconds; making this timeout short fixes the issue, but
    #       could lead to false negatives in the event that we are on GCE, but
    #       the metadata resolution was particularly slow. The latter case is
    #       "unlikely".
    connection = six.moves.http_client.HTTPConnection(
        _GCE_METADATA_HOST, timeout=1)

    try:
        headers = {_METADATA_FLAVOR_HEADER: _DESIRED_METADATA_FLAVOR}
        connection.request('GET', '/', headers=headers)
        response = connection.getresponse()
        if response.status == 200:
            return (response.getheader(_METADATA_FLAVOR_HEADER) ==
                    _DESIRED_METADATA_FLAVOR)
    except socket.error:  # socket.timeout or socket.error(64, 'Host is down')
        logger.info('Timeout attempting to reach GCE metadata service.')
        return False
    finally:
        connection.close()


def _in_gae_environment():
    """Detects if the code is running in the App Engine environment.

    Returns:
        True if running in the GAE environment, False otherwise.
    """
    if SETTINGS.env_name is not None:
        return SETTINGS.env_name in ('GAE_PRODUCTION', 'GAE_LOCAL')

    try:
        import google.appengine  # noqa: unused import
    except ImportError:
        pass
    else:
        server_software = os.environ.get(_SERVER_SOFTWARE, '')
        if server_software.startswith('Google App Engine/'):
            SETTINGS.env_name = 'GAE_PRODUCTION'
            return True
        elif server_software.startswith('Development/'):
            SETTINGS.env_name = 'GAE_LOCAL'
            return True

    return False


def _in_gce_environment():
    """Detect if the code is running in the Compute Engine environment.

    Returns:
        True if running in the GCE environment, False otherwise.
    """
    if SETTINGS.env_name is not None:
        return SETTINGS.env_name == 'GCE_PRODUCTION'

    if NO_GCE_CHECK != 'True' and _detect_gce_environment():
        SETTINGS.env_name = 'GCE_PRODUCTION'
        return True
    return False


class GoogleCredentials(OAuth2Credentials):
    """Application Default Credentials for use in calling Google APIs.

    The Application Default Credentials are being constructed as a function of
    the environment where the code is being run.
    More details can be found on this page:
    https://developers.google.com/accounts/docs/application-default-credentials

    Here is an example of how to use the Application Default Credentials for a
    service that requires authentication::

        from googleapiclient.discovery import build
        from oauth2client.client import GoogleCredentials

        credentials = GoogleCredentials.get_application_default()
        service = build('compute', 'v1', credentials=credentials)

        PROJECT = 'bamboo-machine-422'
        ZONE = 'us-central1-a'
        request = service.instances().list(project=PROJECT, zone=ZONE)
        response = request.execute()

        print(response)
    """

    def __init__(self, access_token, client_id, client_secret, refresh_token,
                 token_expiry, token_uri, user_agent,
                 revoke_uri=GOOGLE_REVOKE_URI):
        """Create an instance of GoogleCredentials.

        This constructor is not usually called by the user, instead
        GoogleCredentials objects are instantiated by
        GoogleCredentials.from_stream() or
        GoogleCredentials.get_application_default().

        Args:
            access_token: string, access token.
            client_id: string, client identifier.
            client_secret: string, client secret.
            refresh_token: string, refresh token.
            token_expiry: datetime, when the access_token expires.
            token_uri: string, URI of token endpoint.
            user_agent: string, The HTTP User-Agent to provide for this
                        application.
            revoke_uri: string, URI for revoke endpoint. Defaults to
                        GOOGLE_REVOKE_URI; a token can't be revoked if this
                        is None.
        """
        super(GoogleCredentials, self).__init__(
            access_token, client_id, client_secret, refresh_token,
            token_expiry, token_uri, user_agent, revoke_uri=revoke_uri)

    def create_scoped_required(self):
        """Whether this Credentials object is scopeless.

        create_scoped(scopes) method needs to be called in order to create
        a Credentials object for API calls.
        """
        return False

    def create_scoped(self, scopes):
        """Create a Credentials object for the given scopes.

        The Credentials type is preserved.
        """
        return self

    @property
    def serialization_data(self):
        """Get the fields and values identifying the current credentials."""
        return {
            'type': 'authorized_user',
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'refresh_token': self.refresh_token
        }

    @staticmethod
    def _implicit_credentials_from_gae():
        """Attempts to get implicit credentials in Google App Engine env.

        If the current environment is not detected as App Engine, returns None,
        indicating no Google App Engine credentials can be detected from the
        current environment.

        Returns:
            None, if not in GAE, else an appengine.AppAssertionCredentials
            object.
        """
        if not _in_gae_environment():
            return None

        return _get_application_default_credential_GAE()

    @staticmethod
    def _implicit_credentials_from_gce():
        """Attempts to get implicit credentials in Google Compute Engine env.

        If the current environment is not detected as Compute Engine, returns
        None, indicating no Google Compute Engine credentials can be detected
        from the current environment.

        Returns:
            None, if not in GCE, else a gce.AppAssertionCredentials object.
        """
        if not _in_gce_environment():
            return None

        return _get_application_default_credential_GCE()

    @staticmethod
    def _implicit_credentials_from_files():
        """Attempts to get implicit credentials from local credential files.

        First checks if the environment variable GOOGLE_APPLICATION_CREDENTIALS
        is set with a filename and then falls back to a configuration file (the
        "well known" file) associated with the 'gcloud' command line tool.

        Returns:
            Credentials object associated with the
            GOOGLE_APPLICATION_CREDENTIALS file or the "well known" file if
            either exist. If neither file is define, returns None, indicating
            no credentials from a file can detected from the current
            environment.
        """
        credentials_filename = _get_environment_variable_file()
        if not credentials_filename:
            credentials_filename = _get_well_known_file()
            if os.path.isfile(credentials_filename):
                extra_help = (' (produced automatically when running'
                              ' "gcloud auth login" command)')
            else:
                credentials_filename = None
        else:
            extra_help = (' (pointed to by ' + GOOGLE_APPLICATION_CREDENTIALS +
                          ' environment variable)')

        if not credentials_filename:
            return

        # If we can read the credentials from a file, we don't need to know
        # what environment we are in.
        SETTINGS.env_name = DEFAULT_ENV_NAME

        try:
            return _get_application_default_credential_from_file(
                credentials_filename)
        except (ApplicationDefaultCredentialsError, ValueError) as error:
            _raise_exception_for_reading_json(credentials_filename,
                                              extra_help, error)

    @classmethod
    def _get_implicit_credentials(cls):
        """Gets credentials implicitly from the environment.

        Checks environment in order of precedence:
        - Google App Engine (production and testing)
        - Environment variable GOOGLE_APPLICATION_CREDENTIALS pointing to
          a file with stored credentials information.
        - Stored "well known" file associated with `gcloud` command line tool.
        - Google Compute Engine production environment.

        Raises:
            ApplicationDefaultCredentialsError: raised when the credentials
                                                fail to be retrieved.
        """
        # Environ checks (in order).
        environ_checkers = [
            cls._implicit_credentials_from_gae,
            cls._implicit_credentials_from_files,
            cls._implicit_credentials_from_gce,
        ]

        for checker in environ_checkers:
            credentials = checker()
            if credentials is not None:
                return credentials

        # If no credentials, fail.
        raise ApplicationDefaultCredentialsError(ADC_HELP_MSG)

    @staticmethod
    def get_application_default():
        """Get the Application Default Credentials for the current environment.

        Raises:
            ApplicationDefaultCredentialsError: raised when the credentials
                                                fail to be retrieved.
        """
        return GoogleCredentials._get_implicit_credentials()

    @staticmethod
    def from_stream(credential_filename):
        """Create a Credentials object by reading information from a file.

        It returns an object of type GoogleCredentials.

        Args:
            credential_filename: the path to the file from where the
                                 credentials are to be read

        Raises:
            ApplicationDefaultCredentialsError: raised when the credentials
                                                fail to be retrieved.
        """
        if credential_filename and os.path.isfile(credential_filename):
            try:
                return _get_application_default_credential_from_file(
                    credential_filename)
            except (ApplicationDefaultCredentialsError, ValueError) as error:
                extra_help = (' (provided as parameter to the '
                              'from_stream() method)')
                _raise_exception_for_reading_json(credential_filename,
                                                  extra_help,
                                                  error)
        else:
            raise ApplicationDefaultCredentialsError(
                'The parameter passed to the from_stream() '
                'method should point to a file.')


def _save_private_file(filename, json_contents):
    """Saves a file with read-write permissions on for the owner.

    Args:
        filename: String. Absolute path to file.
        json_contents: JSON serializable object to be saved.
    """
    temp_filename = tempfile.mktemp()
    file_desc = os.open(temp_filename, os.O_WRONLY | os.O_CREAT, 0o600)
    with os.fdopen(file_desc, 'w') as file_handle:
        json.dump(json_contents, file_handle, sort_keys=True,
                  indent=2, separators=(',', ': '))
    shutil.move(temp_filename, filename)


def save_to_well_known_file(credentials, well_known_file=None):
    """Save the provided GoogleCredentials to the well known file.

    Args:
        credentials: the credentials to be saved to the well known file;
                     it should be an instance of GoogleCredentials
        well_known_file: the name of the file where the credentials are to be
                         saved; this parameter is supposed to be used for
                         testing only
    """
    # TODO(orestica): move this method to tools.py
    # once the argparse import gets fixed (it is not present in Python 2.6)

    if well_known_file is None:
        well_known_file = _get_well_known_file()

    config_dir = os.path.dirname(well_known_file)
    if not os.path.isdir(config_dir):
        raise OSError('Config directory does not exist: %s' % config_dir)

    credentials_data = credentials.serialization_data
    _save_private_file(well_known_file, credentials_data)


def _get_environment_variable_file():
    application_default_credential_filename = (
      os.environ.get(GOOGLE_APPLICATION_CREDENTIALS,
                     None))

    if application_default_credential_filename:
        if os.path.isfile(application_default_credential_filename):
            return application_default_credential_filename
        else:
            raise ApplicationDefaultCredentialsError(
                'File ' + application_default_credential_filename +
                ' (pointed by ' +
                GOOGLE_APPLICATION_CREDENTIALS +
                ' environment variable) does not exist!')


def _get_well_known_file():
    """Get the well known file produced by command 'gcloud auth login'."""
    # TODO(orestica): Revisit this method once gcloud provides a better way
    # of pinpointing the exact location of the file.

    WELL_KNOWN_CREDENTIALS_FILE = 'application_default_credentials.json'

    default_config_dir = os.getenv(_CLOUDSDK_CONFIG_ENV_VAR)
    if default_config_dir is None:
        if os.name == 'nt':
            try:
                default_config_dir = os.path.join(os.environ['APPDATA'],
                                                  _CLOUDSDK_CONFIG_DIRECTORY)
            except KeyError:
                # This should never happen unless someone is really
                # messing with things.
                drive = os.environ.get('SystemDrive', 'C:')
                default_config_dir = os.path.join(drive, '\\',
                                                  _CLOUDSDK_CONFIG_DIRECTORY)
        else:
            default_config_dir = os.path.join(os.path.expanduser('~'),
                                              '.config',
                                              _CLOUDSDK_CONFIG_DIRECTORY)

    return os.path.join(default_config_dir, WELL_KNOWN_CREDENTIALS_FILE)


def _get_application_default_credential_from_file(filename):
    """Build the Application Default Credentials from file."""

    from oauth2client import service_account

    # read the credentials from the file
    with open(filename) as file_obj:
        client_credentials = json.load(file_obj)

    credentials_type = client_credentials.get('type')
    if credentials_type == AUTHORIZED_USER:
        required_fields = set(['client_id', 'client_secret', 'refresh_token'])
    elif credentials_type == SERVICE_ACCOUNT:
        required_fields = set(['client_id', 'client_email', 'private_key_id',
                               'private_key'])
    else:
        raise ApplicationDefaultCredentialsError(
            "'type' field should be defined (and have one of the '" +
            AUTHORIZED_USER + "' or '" + SERVICE_ACCOUNT + "' values)")

    missing_fields = required_fields.difference(client_credentials.keys())

    if missing_fields:
        _raise_exception_for_missing_fields(missing_fields)

    if client_credentials['type'] == AUTHORIZED_USER:
        return GoogleCredentials(
            access_token=None,
            client_id=client_credentials['client_id'],
            client_secret=client_credentials['client_secret'],
            refresh_token=client_credentials['refresh_token'],
            token_expiry=None,
            token_uri=GOOGLE_TOKEN_URI,
            user_agent='Python client library')
    else:  # client_credentials['type'] == SERVICE_ACCOUNT
        return service_account._ServiceAccountCredentials(
            service_account_id=client_credentials['client_id'],
            service_account_email=client_credentials['client_email'],
            private_key_id=client_credentials['private_key_id'],
            private_key_pkcs8_text=client_credentials['private_key'],
            scopes=[])


def _raise_exception_for_missing_fields(missing_fields):
    raise ApplicationDefaultCredentialsError(
        'The following field(s) must be defined: ' + ', '.join(missing_fields))


def _raise_exception_for_reading_json(credential_file,
                                      extra_help,
                                      error):
    raise ApplicationDefaultCredentialsError(
      'An error was encountered while reading json file: ' +
      credential_file + extra_help + ': ' + str(error))


def _get_application_default_credential_GAE():
    from oauth2client.appengine import AppAssertionCredentials

    return AppAssertionCredentials([])


def _get_application_default_credential_GCE():
    from oauth2client.gce import AppAssertionCredentials

    return AppAssertionCredentials([])


class AssertionCredentials(GoogleCredentials):
    """Abstract Credentials object used for OAuth 2.0 assertion grants.

    This credential does not require a flow to instantiate because it
    represents a two legged flow, and therefore has all of the required
    information to generate and refresh its own access tokens. It must
    be subclassed to generate the appropriate assertion string.

    AssertionCredentials objects may be safely pickled and unpickled.
    """

    @util.positional(2)
    def __init__(self, assertion_type, user_agent=None,
                 token_uri=GOOGLE_TOKEN_URI,
                 revoke_uri=GOOGLE_REVOKE_URI,
                 **unused_kwargs):
        """Constructor for AssertionFlowCredentials.

        Args:
            assertion_type: string, assertion type that will be declared to the
                            auth server
            user_agent: string, The HTTP User-Agent to provide for this
                        application.
            token_uri: string, URI for token endpoint. For convenience defaults
                       to Google's endpoints but any OAuth 2.0 provider can be
                       used.
            revoke_uri: string, URI for revoke endpoint.
        """
        super(AssertionCredentials, self).__init__(
            None,
            None,
            None,
            None,
            None,
            token_uri,
            user_agent,
            revoke_uri=revoke_uri)
        self.assertion_type = assertion_type

    def _generate_refresh_request_body(self):
        assertion = self._generate_assertion()

        body = urllib.parse.urlencode({
            'assertion': assertion,
            'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        })

        return body

    def _generate_assertion(self):
        """Generate assertion string to be used in the access token request."""
        _abstract()

    def _revoke(self, http_request):
        """Revokes the access_token and deletes the store if available.

        Args:
            http_request: callable, a callable that matches the method
                          signature of httplib2.Http.request, used to make the
                          revoke request.
        """
        self._do_revoke(http_request, self.access_token)


def _RequireCryptoOrDie():
    """Ensure we have a crypto library, or throw CryptoUnavailableError.

    The oauth2client.crypt module requires either PyCrypto or PyOpenSSL
    to be available in order to function, but these are optional
    dependencies.
    """
    if not HAS_CRYPTO:
        raise CryptoUnavailableError('No crypto library available')


class SignedJwtAssertionCredentials(AssertionCredentials):
    """Credentials object used for OAuth 2.0 Signed JWT assertion grants.

    This credential does not require a flow to instantiate because it
    represents a two legged flow, and therefore has all of the required
    information to generate and refresh its own access tokens.

    SignedJwtAssertionCredentials requires either PyOpenSSL, or PyCrypto
    2.6 or later. For App Engine you may also consider using
    AppAssertionCredentials.
    """

    MAX_TOKEN_LIFETIME_SECS = 3600  # 1 hour in seconds

    @util.positional(4)
    def __init__(self,
                 service_account_name,
                 private_key,
                 scope,
                 private_key_password='notasecret',
                 user_agent=None,
                 token_uri=GOOGLE_TOKEN_URI,
                 revoke_uri=GOOGLE_REVOKE_URI,
                 **kwargs):
        """Constructor for SignedJwtAssertionCredentials.

        Args:
            service_account_name: string, id for account, usually an email
                                  address.
            private_key: string or bytes, private key in PKCS12 or PEM format.
            scope: string or iterable of strings, scope(s) of the credentials
                   being requested.
            private_key_password: string, password for private_key, unused if
                                  private_key is in PEM format.
            user_agent: string, HTTP User-Agent to provide for this
                        application.
            token_uri: string, URI for token endpoint. For convenience defaults
                       to Google's endpoints but any OAuth 2.0 provider can be
                       used.
            revoke_uri: string, URI for revoke endpoint.
            kwargs: kwargs, Additional parameters to add to the JWT token, for
                    example sub=joe@xample.org.

        Raises:
            CryptoUnavailableError if no crypto library is available.
        """
        _RequireCryptoOrDie()
        super(SignedJwtAssertionCredentials, self).__init__(
            None,
            user_agent=user_agent,
            token_uri=token_uri,
            revoke_uri=revoke_uri,
        )

        self.scope = util.scopes_to_string(scope)

        # Keep base64 encoded so it can be stored in JSON.
        self.private_key = base64.b64encode(_to_bytes(private_key))
        self.private_key_password = private_key_password
        self.service_account_name = service_account_name
        self.kwargs = kwargs

    @classmethod
    def from_json(cls, s):
        data = json.loads(_from_bytes(s))
        retval = SignedJwtAssertionCredentials(
            data['service_account_name'],
            base64.b64decode(data['private_key']),
            data['scope'],
            private_key_password=data['private_key_password'],
            user_agent=data['user_agent'],
            token_uri=data['token_uri'],
            **data['kwargs']
        )
        retval.invalid = data['invalid']
        retval.access_token = data['access_token']
        return retval

    def _generate_assertion(self):
        """Generate the assertion that will be used in the request."""
        now = int(time.time())
        payload = {
            'aud': self.token_uri,
            'scope': self.scope,
            'iat': now,
            'exp': now + SignedJwtAssertionCredentials.MAX_TOKEN_LIFETIME_SECS,
            'iss': self.service_account_name
        }
        payload.update(self.kwargs)
        logger.debug(str(payload))

        private_key = base64.b64decode(self.private_key)
        return crypt.make_signed_jwt(crypt.Signer.from_string(
            private_key, self.private_key_password), payload)

# Only used in verify_id_token(), which is always calling to the same URI
# for the certs.
_cached_http = httplib2.Http(MemoryCache())


@util.positional(2)
def verify_id_token(id_token, audience, http=None,
                    cert_uri=ID_TOKEN_VERIFICATION_CERTS):
    """Verifies a signed JWT id_token.

    This function requires PyOpenSSL and because of that it does not work on
    App Engine.

    Args:
        id_token: string, A Signed JWT.
        audience: string, The audience 'aud' that the token should be for.
        http: httplib2.Http, instance to use to make the HTTP request. Callers
              should supply an instance that has caching enabled.
        cert_uri: string, URI of the certificates in JSON format to
                  verify the JWT against.

    Returns:
        The deserialized JSON in the JWT.

    Raises:
        oauth2client.crypt.AppIdentityError: if the JWT fails to verify.
        CryptoUnavailableError: if no crypto library is available.
    """
    _RequireCryptoOrDie()
    if http is None:
        http = _cached_http

    resp, content = http.request(cert_uri)
    if resp.status == 200:
        certs = json.loads(_from_bytes(content))
        return crypt.verify_signed_jwt_with_certs(id_token, certs, audience)
    else:
        raise VerifyJwtTokenError('Status code: %d' % resp.status)


def _extract_id_token(id_token):
    """Extract the JSON payload from a JWT.

    Does the extraction w/o checking the signature.

    Args:
        id_token: string or bytestring, OAuth 2.0 id_token.

    Returns:
        object, The deserialized JSON payload.
    """
    if type(id_token) == bytes:
        segments = id_token.split(b'.')
    else:
        segments = id_token.split(u'.')

    if len(segments) != 3:
        raise VerifyJwtTokenError(
            'Wrong number of segments in token: %s' % id_token)

    return json.loads(_from_bytes(_urlsafe_b64decode(segments[1])))


def _parse_exchange_token_response(content):
    """Parses response of an exchange token request.

    Most providers return JSON but some (e.g. Facebook) return a
    url-encoded string.

    Args:
        content: The body of a response

    Returns:
        Content as a dictionary object. Note that the dict could be empty,
        i.e. {}. That basically indicates a failure.
    """
    resp = {}
    content = _from_bytes(content)
    try:
        resp = json.loads(content)
    except Exception:
        # different JSON libs raise different exceptions,
        # so we just do a catch-all here
        resp = dict(urllib.parse.parse_qsl(content))

    # some providers respond with 'expires', others with 'expires_in'
    if resp and 'expires' in resp:
        resp['expires_in'] = resp.pop('expires')

    return resp


@util.positional(4)
def credentials_from_code(client_id, client_secret, scope, code,
                          redirect_uri='postmessage', http=None,
                          user_agent=None, token_uri=GOOGLE_TOKEN_URI,
                          auth_uri=GOOGLE_AUTH_URI,
                          revoke_uri=GOOGLE_REVOKE_URI,
                          device_uri=GOOGLE_DEVICE_URI,
                          token_info_uri=GOOGLE_TOKEN_INFO_URI):
    """Exchanges an authorization code for an OAuth2Credentials object.

    Args:
        client_id: string, client identifier.
        client_secret: string, client secret.
        scope: string or iterable of strings, scope(s) to request.
        code: string, An authorization code, most likely passed down from
              the client
        redirect_uri: string, this is generally set to 'postmessage' to match
                      the redirect_uri that the client specified
        http: httplib2.Http, optional http instance to use to do the fetch
        token_uri: string, URI for token endpoint. For convenience defaults
                   to Google's endpoints but any OAuth 2.0 provider can be
                   used.
        auth_uri: string, URI for authorization endpoint. For convenience
                  defaults to Google's endpoints but any OAuth 2.0 provider
                  can be used.
        revoke_uri: string, URI for revoke endpoint. For convenience
                    defaults to Google's endpoints but any OAuth 2.0 provider
                    can be used.
        device_uri: string, URI for device authorization endpoint. For
                    convenience defaults to Google's endpoints but any OAuth
                    2.0 provider can be used.

    Returns:
        An OAuth2Credentials object.

    Raises:
        FlowExchangeError if the authorization code cannot be exchanged for an
        access token
    """
    flow = OAuth2WebServerFlow(client_id, client_secret, scope,
                               redirect_uri=redirect_uri,
                               user_agent=user_agent, auth_uri=auth_uri,
                               token_uri=token_uri, revoke_uri=revoke_uri,
                               device_uri=device_uri,
                               token_info_uri=token_info_uri)

    credentials = flow.step2_exchange(code, http=http)
    return credentials


@util.positional(3)
def credentials_from_clientsecrets_and_code(filename, scope, code,
                                            message=None,
                                            redirect_uri='postmessage',
                                            http=None,
                                            cache=None,
                                            device_uri=None):
    """Returns OAuth2Credentials from a clientsecrets file and an auth code.

    Will create the right kind of Flow based on the contents of the
    clientsecrets file or will raise InvalidClientSecretsError for unknown
    types of Flows.

    Args:
        filename: string, File name of clientsecrets.
        scope: string or iterable of strings, scope(s) to request.
        code: string, An authorization code, most likely passed down from
              the client
        message: string, A friendly string to display to the user if the
                 clientsecrets file is missing or invalid. If message is
                 provided then sys.exit will be called in the case of an error.
                 If message in not provided then
                 clientsecrets.InvalidClientSecretsError will be raised.
        redirect_uri: string, this is generally set to 'postmessage' to match
                      the redirect_uri that the client specified
        http: httplib2.Http, optional http instance to use to do the fetch
        cache: An optional cache service client that implements get() and set()
               methods. See clientsecrets.loadfile() for details.
        device_uri: string, OAuth 2.0 device authorization endpoint

    Returns:
        An OAuth2Credentials object.

    Raises:
        FlowExchangeError: if the authorization code cannot be exchanged for an
                           access token
        UnknownClientSecretsFlowError: if the file describes an unknown kind
                                       of Flow.
        clientsecrets.InvalidClientSecretsError: if the clientsecrets file is
                                                 invalid.
    """
    flow = flow_from_clientsecrets(filename, scope, message=message,
                                   cache=cache, redirect_uri=redirect_uri,
                                   device_uri=device_uri)
    credentials = flow.step2_exchange(code, http=http)
    return credentials


class DeviceFlowInfo(collections.namedtuple('DeviceFlowInfo', (
        'device_code', 'user_code', 'interval', 'verification_url',
        'user_code_expiry'))):
    """Intermediate information the OAuth2 for devices flow."""

    @classmethod
    def FromResponse(cls, response):
        """Create a DeviceFlowInfo from a server response.

        The response should be a dict containing entries as described here:

        http://tools.ietf.org/html/draft-ietf-oauth-v2-05#section-3.7.1
        """
        # device_code, user_code, and verification_url are required.
        kwargs = {
            'device_code': response['device_code'],
            'user_code': response['user_code'],
        }
        # The response may list the verification address as either
        # verification_url or verification_uri, so we check for both.
        verification_url = response.get(
            'verification_url', response.get('verification_uri'))
        if verification_url is None:
            raise OAuth2DeviceCodeError(
                'No verification_url provided in server response')
        kwargs['verification_url'] = verification_url
        # expires_in and interval are optional.
        kwargs.update({
            'interval': response.get('interval'),
            'user_code_expiry': None,
        })
        if 'expires_in' in response:
            kwargs['user_code_expiry'] = (
                datetime.datetime.now() +
                datetime.timedelta(seconds=int(response['expires_in'])))
        return cls(**kwargs)


class OAuth2WebServerFlow(Flow):
    """Does the Web Server Flow for OAuth 2.0.

    OAuth2WebServerFlow objects may be safely pickled and unpickled.
    """

    @util.positional(4)
    def __init__(self, client_id,
                 client_secret=None,
                 scope=None,
                 redirect_uri=None,
                 user_agent=None,
                 auth_uri=GOOGLE_AUTH_URI,
                 token_uri=GOOGLE_TOKEN_URI,
                 revoke_uri=GOOGLE_REVOKE_URI,
                 login_hint=None,
                 device_uri=GOOGLE_DEVICE_URI,
                 token_info_uri=GOOGLE_TOKEN_INFO_URI,
                 authorization_header=None,
                 **kwargs):
        """Constructor for OAuth2WebServerFlow.

        The kwargs argument is used to set extra query parameters on the
        auth_uri. For example, the access_type and approval_prompt
        query parameters can be set via kwargs.

        Args:
            client_id: string, client identifier.
            client_secret: string client secret.
            scope: string or iterable of strings, scope(s) of the credentials
                   being requested.
            redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob'
                          for a non-web-based application, or a URI that
                          handles the callback from the authorization server.
            user_agent: string, HTTP User-Agent to provide for this
                        application.
            auth_uri: string, URI for authorization endpoint. For convenience
                      defaults to Google's endpoints but any OAuth 2.0 provider
                      can be used.
            token_uri: string, URI for token endpoint. For convenience
                       defaults to Google's endpoints but any OAuth 2.0
                       provider can be used.
            revoke_uri: string, URI for revoke endpoint. For convenience
                        defaults to Google's endpoints but any OAuth 2.0
                        provider can be used.
            login_hint: string, Either an email address or domain. Passing this
                        hint will either pre-fill the email box on the sign-in
                        form or select the proper multi-login session, thereby
                        simplifying the login flow.
            device_uri: string, URI for device authorization endpoint. For
                        convenience defaults to Google's endpoints but any
                        OAuth 2.0 provider can be used.
            authorization_header: string, For use with OAuth 2.0 providers that
                                  require a client to authenticate using a
                                  header value instead of passing client_secret
                                  in the POST body.
            **kwargs: dict, The keyword arguments are all optional and required
                      parameters for the OAuth calls.
        """
        # scope is a required argument, but to preserve backwards-compatibility
        # we don't want to rearrange the positional arguments
        if scope is None:
            raise TypeError("The value of scope must not be None")
        self.client_id = client_id
        self.client_secret = client_secret
        self.scope = util.scopes_to_string(scope)
        self.redirect_uri = redirect_uri
        self.login_hint = login_hint
        self.user_agent = user_agent
        self.auth_uri = auth_uri
        self.token_uri = token_uri
        self.revoke_uri = revoke_uri
        self.device_uri = device_uri
        self.token_info_uri = token_info_uri
        self.authorization_header = authorization_header
        self.params = {
            'access_type': 'offline',
            'response_type': 'code',
        }
        self.params.update(kwargs)

    @util.positional(1)
    def step1_get_authorize_url(self, redirect_uri=None, state=None):
        """Returns a URI to redirect to the provider.

        Args:
            redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob'
                          for a non-web-based application, or a URI that
                          handles the callback from the authorization server.
                          This parameter is deprecated, please move to passing
                          the redirect_uri in via the constructor.
            state: string, Opaque state string which is passed through the
                   OAuth2 flow and returned to the client as a query parameter
                   in the callback.

        Returns:
            A URI as a string to redirect the user to begin the authorization
            flow.
        """
        if redirect_uri is not None:
            logger.warning((
                'The redirect_uri parameter for '
                'OAuth2WebServerFlow.step1_get_authorize_url is deprecated. '
                'Please move to passing the redirect_uri in via the '
                'constructor.'))
            self.redirect_uri = redirect_uri

        if self.redirect_uri is None:
            raise ValueError('The value of redirect_uri must not be None.')

        query_params = {
            'client_id': self.client_id,
            'redirect_uri': self.redirect_uri,
            'scope': self.scope,
        }
        if state is not None:
            query_params['state'] = state
        if self.login_hint is not None:
            query_params['login_hint'] = self.login_hint
        query_params.update(self.params)
        return _update_query_params(self.auth_uri, query_params)

    @util.positional(1)
    def step1_get_device_and_user_codes(self, http=None):
        """Returns a user code and the verification URL where to enter it

        Returns:
            A user code as a string for the user to authorize the application
            An URL as a string where the user has to enter the code
        """
        if self.device_uri is None:
            raise ValueError('The value of device_uri must not be None.')

        body = urllib.parse.urlencode({
            'client_id': self.client_id,
            'scope': self.scope,
        })
        headers = {
            'content-type': 'application/x-www-form-urlencoded',
        }

        if self.user_agent is not None:
            headers['user-agent'] = self.user_agent

        if http is None:
            http = httplib2.Http()

        resp, content = http.request(self.device_uri, method='POST', body=body,
                                     headers=headers)
        content = _from_bytes(content)
        if resp.status == 200:
            try:
                flow_info = json.loads(content)
            except ValueError as e:
                raise OAuth2DeviceCodeError(
                    'Could not parse server response as JSON: "%s", '
                    'error: "%s"' % (content, e))
            return DeviceFlowInfo.FromResponse(flow_info)
        else:
            error_msg = 'Invalid response %s.' % resp.status
            try:
                d = json.loads(content)
                if 'error' in d:
                    error_msg += ' Error: %s' % d['error']
            except ValueError:
                # Couldn't decode a JSON response, stick with the
                # default message.
                pass
            raise OAuth2DeviceCodeError(error_msg)

    @util.positional(2)
    def step2_exchange(self, code=None, http=None, device_flow_info=None):
        """Exchanges a code for OAuth2Credentials.

        Args:
            code: string, a dict-like object, or None. For a non-device
                  flow, this is either the response code as a string, or a
                  dictionary of query parameters to the redirect_uri. For a
                  device flow, this should be None.
            http: httplib2.Http, optional http instance to use when fetching
                  credentials.
            device_flow_info: DeviceFlowInfo, return value from step1 in the
                              case of a device flow.

        Returns:
            An OAuth2Credentials object that can be used to authorize requests.

        Raises:
            FlowExchangeError: if a problem occurred exchanging the code for a
                               refresh_token.
            ValueError: if code and device_flow_info are both provided or both
                        missing.
        """
        if code is None and device_flow_info is None:
            raise ValueError('No code or device_flow_info provided.')
        if code is not None and device_flow_info is not None:
            raise ValueError('Cannot provide both code and device_flow_info.')

        if code is None:
            code = device_flow_info.device_code
        elif not isinstance(code, six.string_types):
            if 'code' not in code:
                raise FlowExchangeError(code.get(
                    'error', 'No code was supplied in the query parameters.'))
            code = code['code']

        post_data = {
            'client_id': self.client_id,
            'code': code,
            'scope': self.scope,
        }
        if self.client_secret is not None:
            post_data['client_secret'] = self.client_secret
        if device_flow_info is not None:
            post_data['grant_type'] = 'http://oauth.net/grant_type/device/1.0'
        else:
            post_data['grant_type'] = 'authorization_code'
            post_data['redirect_uri'] = self.redirect_uri
        body = urllib.parse.urlencode(post_data)
        headers = {
            'content-type': 'application/x-www-form-urlencoded',
        }
        if self.authorization_header is not None:
            headers['Authorization'] = self.authorization_header
        if self.user_agent is not None:
            headers['user-agent'] = self.user_agent

        if http is None:
            http = httplib2.Http()

        resp, content = http.request(self.token_uri, method='POST', body=body,
                                     headers=headers)
        d = _parse_exchange_token_response(content)
        if resp.status == 200 and 'access_token' in d:
            access_token = d['access_token']
            refresh_token = d.get('refresh_token', None)
            if not refresh_token:
                logger.info(
                    'Received token response with no refresh_token. Consider '
                    "reauthenticating with approval_prompt='force'.")
            token_expiry = None
            if 'expires_in' in d:
                token_expiry = (
                    datetime.datetime.utcnow() +
                    datetime.timedelta(seconds=int(d['expires_in'])))

            extracted_id_token = None
            if 'id_token' in d:
                extracted_id_token = _extract_id_token(d['id_token'])

            logger.info('Successfully retrieved access token')
            return OAuth2Credentials(
                access_token, self.client_id, self.client_secret,
                refresh_token, token_expiry, self.token_uri, self.user_agent,
                revoke_uri=self.revoke_uri, id_token=extracted_id_token,
                token_response=d, scopes=self.scope,
                token_info_uri=self.token_info_uri)
        else:
            logger.info('Failed to retrieve access token: %s', content)
            if 'error' in d:
                # you never know what those providers got to say
                error_msg = (str(d['error']) +
                             str(d.get('error_description', '')))
            else:
                error_msg = 'Invalid response: %s.' % str(resp.status)
            raise FlowExchangeError(error_msg)


@util.positional(2)
def flow_from_clientsecrets(filename, scope, redirect_uri=None,
                            message=None, cache=None, login_hint=None,
                            device_uri=None):
    """Create a Flow from a clientsecrets file.

    Will create the right kind of Flow based on the contents of the
    clientsecrets file or will raise InvalidClientSecretsError for unknown
    types of Flows.

    Args:
        filename: string, File name of client secrets.
        scope: string or iterable of strings, scope(s) to request.
        redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for
                      a non-web-based application, or a URI that handles the
                      callback from the authorization server.
        message: string, A friendly string to display to the user if the
                 clientsecrets file is missing or invalid. If message is
                 provided then sys.exit will be called in the case of an error.
                 If message in not provided then
                 clientsecrets.InvalidClientSecretsError will be raised.
        cache: An optional cache service client that implements get() and set()
               methods. See clientsecrets.loadfile() for details.
        login_hint: string, Either an email address or domain. Passing this
                    hint will either pre-fill the email box on the sign-in form
                    or select the proper multi-login session, thereby
                    simplifying the login flow.
        device_uri: string, URI for device authorization endpoint. For
                    convenience defaults to Google's endpoints but any
                    OAuth 2.0 provider can be used.

    Returns:
        A Flow object.

    Raises:
        UnknownClientSecretsFlowError: if the file describes an unknown kind of
                                       Flow.
        clientsecrets.InvalidClientSecretsError: if the clientsecrets file is
                                                 invalid.
    """
    try:
        client_type, client_info = clientsecrets.loadfile(filename,
                                                          cache=cache)
        if client_type in (clientsecrets.TYPE_WEB,
                           clientsecrets.TYPE_INSTALLED):
            constructor_kwargs = {
                'redirect_uri': redirect_uri,
                'auth_uri': client_info['auth_uri'],
                'token_uri': client_info['token_uri'],
                'login_hint': login_hint,
            }
            revoke_uri = client_info.get('revoke_uri')
            if revoke_uri is not None:
                constructor_kwargs['revoke_uri'] = revoke_uri
            if device_uri is not None:
                constructor_kwargs['device_uri'] = device_uri
            return OAuth2WebServerFlow(
                client_info['client_id'], client_info['client_secret'],
                scope, **constructor_kwargs)

    except clientsecrets.InvalidClientSecretsError:
        if message:
            sys.exit(message)
        else:
            raise
    else:
        raise UnknownClientSecretsFlowError(
            'This OAuth 2.0 flow is unsupported: %r' % client_type)
