# Copyright 2020 Google LLC
#
# 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.

"""OAuth 2.0 Token Exchange Spec.

This module defines a token exchange utility based on the `OAuth 2.0 Token
Exchange`_ spec. This will be mainly used to exchange external credentials
for GCP access tokens in workload identity pools to access Google APIs.

The implementation will support various types of client authentication as
allowed in the spec.

A deviation on the spec will be for additional Google specific options that
cannot be easily mapped to parameters defined in the RFC.

The returned dictionary response will be based on the `rfc8693 section 2.2.1`_
spec JSON response.

.. _OAuth 2.0 Token Exchange: https://tools.ietf.org/html/rfc8693
.. _rfc8693 section 2.2.1: https://tools.ietf.org/html/rfc8693#section-2.2.1
"""

import json

from six.moves import http_client
from six.moves import urllib

from google.oauth2 import utils


_URLENCODED_HEADERS = {"Content-Type": "application/x-www-form-urlencoded"}


class Client(utils.OAuthClientAuthHandler):
    """Implements the OAuth 2.0 token exchange spec based on
    https://tools.ietf.org/html/rfc8693.
    """

    def __init__(self, token_exchange_endpoint, client_authentication=None):
        """Initializes an STS client instance.

        Args:
            token_exchange_endpoint (str): The token exchange endpoint.
            client_authentication (Optional(google.oauth2.oauth2_utils.ClientAuthentication)):
                The optional OAuth client authentication credentials if available.
        """
        super(Client, self).__init__(client_authentication)
        self._token_exchange_endpoint = token_exchange_endpoint

    def exchange_token(
        self,
        request,
        grant_type,
        subject_token,
        subject_token_type,
        resource=None,
        audience=None,
        scopes=None,
        requested_token_type=None,
        actor_token=None,
        actor_token_type=None,
        additional_options=None,
        additional_headers=None,
    ):
        """Exchanges the provided token for another type of token based on the
        rfc8693 spec.

        Args:
            request (google.auth.transport.Request): A callable used to make
                HTTP requests.
            grant_type (str): The OAuth 2.0 token exchange grant type.
            subject_token (str): The OAuth 2.0 token exchange subject token.
            subject_token_type (str): The OAuth 2.0 token exchange subject token type.
            resource (Optional[str]): The optional OAuth 2.0 token exchange resource field.
            audience (Optional[str]): The optional OAuth 2.0 token exchange audience field.
            scopes (Optional[Sequence[str]]): The optional list of scopes to use.
            requested_token_type (Optional[str]): The optional OAuth 2.0 token exchange requested
                token type.
            actor_token (Optional[str]): The optional OAuth 2.0 token exchange actor token.
            actor_token_type (Optional[str]): The optional OAuth 2.0 token exchange actor token type.
            additional_options (Optional[Mapping[str, str]]): The optional additional
                non-standard Google specific options.
            additional_headers (Optional[Mapping[str, str]]): The optional additional
                headers to pass to the token exchange endpoint.

        Returns:
            Mapping[str, str]: The token exchange JSON-decoded response data containing
                the requested token and its expiration time.

        Raises:
            google.auth.exceptions.OAuthError: If the token endpoint returned
                an error.
        """
        # Initialize request headers.
        headers = _URLENCODED_HEADERS.copy()
        # Inject additional headers.
        if additional_headers:
            for k, v in dict(additional_headers).items():
                headers[k] = v
        # Initialize request body.
        request_body = {
            "grant_type": grant_type,
            "resource": resource,
            "audience": audience,
            "scope": " ".join(scopes or []),
            "requested_token_type": requested_token_type,
            "subject_token": subject_token,
            "subject_token_type": subject_token_type,
            "actor_token": actor_token,
            "actor_token_type": actor_token_type,
            "options": None,
        }
        # Add additional non-standard options.
        if additional_options:
            request_body["options"] = urllib.parse.quote(json.dumps(additional_options))
        # Remove empty fields in request body.
        for k, v in dict(request_body).items():
            if v is None or v == "":
                del request_body[k]
        # Apply OAuth client authentication.
        self.apply_client_authentication_options(headers, request_body)

        # Execute request.
        response = request(
            url=self._token_exchange_endpoint,
            method="POST",
            headers=headers,
            body=urllib.parse.urlencode(request_body).encode("utf-8"),
        )

        response_body = (
            response.data.decode("utf-8")
            if hasattr(response.data, "decode")
            else response.data
        )

        # If non-200 response received, translate to OAuthError exception.
        if response.status != http_client.OK:
            utils.handle_error_response(response_body)

        response_data = json.loads(response_body)

        # Return successful response.
        return response_data
