def _Refresh(self, request):
    if (self._refresh_token is None or self._token_uri is None or
        self._client_id is None or self._client_secret is None):
      raise google_auth_exceptions.RefreshError(
          'The credentials do not contain the necessary fields need to '
          'refresh the access token. You must specify refresh_token, '
          'token_uri, client_id, and client_secret.')
    rapt_token = getattr(self, '_rapt_token', None)
    access_token, refresh_token, expiry, grant_response = _RefreshGrant(
        request, self._token_uri, self._refresh_token, self._client_id,
        self._client_secret, self._scopes, rapt_token)

    self.token = access_token
    self.expiry = expiry
    self._refresh_token = refresh_token
    self._id_token = grant_response.get('id_token')
    # id_token in oauth2client creds is decoded and it uses id_tokenb64 to
    # store the encoded copy. id_token in google-auth creds is encoded.
    # Here, we add id_tokenb64 to google-auth creds for consistency.
    self.id_tokenb64 = grant_response.get('id_token')

    if self._scopes and 'scope' in grant_response:
      requested_scopes = frozenset(self._scopes)
      granted_scopes = frozenset(grant_response['scope'].split())
      scopes_requested_but_not_granted = requested_scopes - granted_scopes
      if scopes_requested_but_not_granted:
        raise google_auth_exceptions.RefreshError(
            'Not all requested scopes were granted by the '
            'authorization server, missing scopes {}.'.format(
                ', '.join(scopes_requested_but_not_granted)))
Beispiel #2
0
    def _get_metadata_role_name(self, request):
        """Retrieves the AWS role currently attached to the current AWS
        workload by querying the AWS metadata server. This is needed for the
        AWS metadata server security credentials endpoint in order to retrieve
        the AWS security credentials needed to sign requests to AWS APIs.

        Args:
            request (google.auth.transport.Request): A callable used to make
                HTTP requests.

        Returns:
            str: The AWS role name.

        Raises:
            google.auth.exceptions.RefreshError: If an error occurs while
                retrieving the AWS role name.
        """
        if self._security_credentials_url is None:
            raise exceptions.RefreshError(
                "Unable to determine the AWS metadata server security credentials endpoint"
            )
        response = request(url=self._security_credentials_url, method="GET")

        # support both string and bytes type response.data
        response_body = (response.data.decode("utf-8") if hasattr(
            response.data, "decode") else response.data)

        if response.status != http.client.OK:
            raise exceptions.RefreshError("Unable to retrieve AWS role name",
                                          response_body)

        return response_body
Beispiel #3
0
    def refresh(self, request):
        if (self._refresh_token is None or self._token_uri is None
                or self._client_id is None or self._client_secret is None):
            raise exceptions.RefreshError(
                "The credentials do not contain the necessary fields need to "
                "refresh the access token. You must specify refresh_token, "
                "token_uri, client_id, and client_secret.")

        access_token, refresh_token, expiry, grant_response = _client.refresh_grant(
            request,
            self._token_uri,
            self._refresh_token,
            self._client_id,
            self._client_secret,
            self._scopes,
        )

        self.token = access_token
        self.expiry = expiry
        self._refresh_token = refresh_token
        self._id_token = grant_response.get("id_token")

        if self._scopes and "scopes" in grant_response:
            requested_scopes = frozenset(self._scopes)
            granted_scopes = frozenset(grant_response["scopes"].split())
            scopes_requested_but_not_granted = requested_scopes - granted_scopes
            if scopes_requested_but_not_granted:
                raise exceptions.RefreshError(
                    "Not all requested scopes were granted by the "
                    "authorization server, missing scopes {}.".format(
                        ", ".join(scopes_requested_but_not_granted)))
    def refresh(self, request):
        if (self._refresh_token is None or
                self._token_uri is None or
                self._client_id is None or
                self._client_secret is None):
            raise exceptions.RefreshError(
                'The credentials do not contain the necessary fields need to '
                'refresh the access token. You must specify refresh_token, '
                'token_uri, client_id, and client_secret.')

        access_token, refresh_token, expiry, grant_response = (
            _client.refresh_grant(
                request, self._token_uri, self._refresh_token, self._client_id,
                self._client_secret, self._scopes))

        self.token = access_token
        self.expiry = expiry
        self._refresh_token = refresh_token
        self._id_token = grant_response.get('id_token')

        if self._scopes and 'scopes' in grant_response:
            requested_scopes = frozenset(self._scopes)
            granted_scopes = frozenset(grant_response['scopes'].split())
            scopes_requested_but_not_granted = (
                requested_scopes - granted_scopes)
            if scopes_requested_but_not_granted:
                raise exceptions.RefreshError(
                    'Not all requested scopes were granted by the '
                    'authorization server, missing scopes {}.'.format(
                        ', '.join(scopes_requested_but_not_granted)))
Beispiel #5
0
def _make_iam_token_request(request,
                            principal,
                            headers,
                            body,
                            iam_endpoint_override=None):
    """Makes a request to the Google Cloud IAM service for an access token.
    Args:
        request (Request): The Request object to use.
        principal (str): The principal to request an access token for.
        headers (Mapping[str, str]): Map of headers to transmit.
        body (Mapping[str, str]): JSON Payload body for the iamcredentials
            API call.
        iam_endpoint_override (Optiona[str]): The full IAM endpoint override
            with the target_principal embedded. This is useful when supporting
            impersonation with regional endpoints.

    Raises:
        google.auth.exceptions.TransportError: Raised if there is an underlying
            HTTP connection error
        google.auth.exceptions.RefreshError: Raised if the impersonated
            credentials are not available.  Common reasons are
            `iamcredentials.googleapis.com` is not enabled or the
            `Service Account Token Creator` is not assigned
    """
    iam_endpoint = iam_endpoint_override or _IAM_ENDPOINT.format(principal)

    body = json.dumps(body).encode("utf-8")

    response = request(url=iam_endpoint,
                       method="POST",
                       headers=headers,
                       body=body)

    # support both string and bytes type response.data
    response_body = (response.data.decode("utf-8") if hasattr(
        response.data, "decode") else response.data)

    if response.status != http_client.OK:
        exceptions.RefreshError(_REFRESH_ERROR, response_body)

    try:
        token_response = json.loads(response_body)
        token = token_response["accessToken"]
        expiry = datetime.strptime(token_response["expireTime"],
                                   "%Y-%m-%dT%H:%M:%SZ")

        return token, expiry

    except (KeyError, ValueError) as caught_exc:
        new_exc = exceptions.RefreshError(
            "{}: No access token or invalid expiration in response.".format(
                _REFRESH_ERROR),
            response_body,
        )
        six.raise_from(new_exc, caught_exc)
Beispiel #6
0
    def _call_metadata_identity_endpoint(self, request):
        """Request ID token from metadata identity endpoint.

        Args:
            request (google.auth.transport.Request): The object used to make
                HTTP requests.

        Raises:
            google.auth.exceptions.RefreshError: If the Compute Engine metadata
                service can't be reached or if the instance has no credentials.
            ValueError: If extracting expiry from the obtained ID token fails.
        """
        try:
            id_token = _metadata.get(
                request,
                "instance/service-accounts/default/identity?audience={}&format=full".format(
                    self._target_audience
                ),
            )
        except exceptions.TransportError as caught_exc:
            new_exc = exceptions.RefreshError(caught_exc)
            six.raise_from(new_exc, caught_exc)

        _, payload, _, _ = jwt._unverified_decode(id_token)
        return id_token, payload["exp"]
Beispiel #7
0
 def testRefreshWithException(self):
     self.StartObjectPatch(
         store,
         'Refresh',
         side_effect=google_auth_exceptions.RefreshError())
     with self.assertRaises(auth_exceptions.AuthenticationError):
         self.Run('auth print-access-token')
Beispiel #8
0
 def test_gather_logs_token_error(self, log_mock):
     """GSuiteReportsApp - Gather Logs, Google API Token Error"""
     with patch.object(self._app, '_activities_service') as service_mock:
         error = exceptions.RefreshError('bad')
         service_mock.list.return_value.execute.side_effect = error
         assert_false(self._app._gather_logs())
         log_mock.assert_called_with('[%s] Failed to execute activities listing', self._app)
 def testRaiseTokenRefreshError(self):
     self.mock_refresh_grant.side_effect = google_auth_exceptions.RefreshError(
         'API error')
     with self.AssertRaisesExceptionMatches(
             c_store.TokenRefreshError,
             '$ gcloud auth application-default login'):
         self.Run('auth application-default print-access-token')
Beispiel #10
0
    def testExceptionHandling(self):
        http_client = HttpClient()
        orig_request = self.StartObjectPatch(http_client,
                                             'request',
                                             return_value={
                                                 'status': httplib.OK,
                                             })
        fake_creds = mock.Mock()
        self.StartObjectPatch(store, 'LoadIfEnabled', return_value=fake_creds)
        RequestWrapper().WrapCredentials(http_client)
        http_client.request('uri', 'method')

        orig_request.side_effect = TypeError
        with self.assertRaises(TypeError):
            http_client.request('uri', 'method')

        orig_request.side_effect = client.AccessTokenRefreshError
        with self.assertRaises(store.TokenRefreshError):
            http_client.request('uri', 'method')

        orig_request.side_effect = google_auth_exceptions.RefreshError
        with self.assertRaises(store.TokenRefreshError):
            http_client.request('uri', 'method')

        orig_request.side_effect = google_auth_exceptions.RefreshError(
            'access_denied: Account restricted')
        with self.assertRaises(store.TokenRefreshDeniedByCAAError):
            http_client.request('uri', 'method')
Beispiel #11
0
def _handle_refresh_grant_response(response_data, refresh_token):
    """Extract tokens from refresh grant response.

    Args:
        response_data (Mapping[str, str]): Refresh grant response data.
        refresh_token (str): Current refresh token.

    Returns:
        Tuple[str, str, Optional[datetime], Mapping[str, str]]: The access token,
            refresh token, expiration, and additional data returned by the token
            endpoint. If response_data doesn't have refresh token, then the current
            refresh token will be returned.

    Raises:
        google.auth.exceptions.RefreshError: If the token endpoint returned
            an error.
    """
    try:
        access_token = response_data["access_token"]
    except KeyError as caught_exc:
        new_exc = exceptions.RefreshError("No access token in response.",
                                          response_data)
        six.raise_from(new_exc, caught_exc)

    refresh_token = response_data.get("refresh_token", refresh_token)
    expiry = _parse_expiry(response_data)

    return access_token, refresh_token, expiry, response_data
Beispiel #12
0
    def _get_file_data(self, filename):
        if not os.path.exists(filename):
            raise exceptions.RefreshError(
                "File '{}' was not found.".format(filename))

        with io.open(filename, "r", encoding="utf-8") as file_obj:
            return file_obj.read(), filename
Beispiel #13
0
def jwt_grant(request, token_uri, assertion):
    """Implements the JWT Profile for OAuth 2.0 Authorization Grants.

    For more details, see `rfc7523 section 4`_.

    Args:
        request (google.auth.transport.Request): A callable used to make
            HTTP requests.
        token_uri (str): The OAuth 2.0 authorizations server's token endpoint
            URI.
        assertion (str): The OAuth 2.0 assertion.

    Returns:
        Tuple[str, Optional[datetime], Mapping[str, str]]: The access token,
            expiration, and additional data returned by the token endpoint.

    Raises:
        google.auth.exceptions.RefreshError: If the token endpoint returned
            an error.

    .. _rfc7523 section 4: https://tools.ietf.org/html/rfc7523#section-4
    """
    body = {"assertion": assertion, "grant_type": _JWT_GRANT_TYPE}

    response_data = _token_endpoint_request(request, token_uri, body)

    try:
        access_token = response_data["access_token"]
    except KeyError as caught_exc:
        new_exc = exceptions.RefreshError("No access token in response.", response_data)
        six.raise_from(new_exc, caught_exc)

    expiry = _parse_expiry(response_data)

    return access_token, expiry, response_data
def _RefreshGrant(request,
                  token_uri,
                  refresh_token,
                  client_id,
                  client_secret,
                  scopes=None,
                  rapt_token=None):
  """Prepares the request to send to auth server to refresh tokens."""
  body = [
      ('grant_type', google_auth_client._REFRESH_GRANT_TYPE),  # pylint: disable=protected-access
      ('client_id', client_id),
      ('client_secret', client_secret),
      ('refresh_token', refresh_token),
  ]
  if scopes:
    body.append(('scope', ' '.join(scopes)))
  if rapt_token:
    body.append(('rapt', rapt_token))
  response_data = _TokenEndpointRequestWithRetry(request, token_uri, body)

  try:
    access_token = response_data['access_token']
  except KeyError as caught_exc:
    new_exc = google_auth_exceptions.RefreshError(
        'No access token in response.', response_data)
    six.raise_from(new_exc, caught_exc)

  refresh_token = response_data.get('refresh_token', refresh_token)
  expiry = google_auth_client._parse_expiry(response_data)  # pylint: disable=protected-access

  return access_token, refresh_token, expiry, response_data
    def _call_metadata_identity_endpoint(self, request):
        """Request ID token from metadata identity endpoint.

        Args:
            request (google.auth.transport.Request): The object used to make
                HTTP requests.

        Returns:
            Tuple[str, datetime.datetime]: The ID token and the expiry of the ID token.

        Raises:
            google.auth.exceptions.RefreshError: If the Compute Engine metadata
                service can't be reached or if the instance has no credentials.
            ValueError: If extracting expiry from the obtained ID token fails.
        """
        try:
            path = "instance/service-accounts/default/identity"
            params = {"audience": self._target_audience, "format": "full"}
            id_token = _metadata.get(request, path, params=params)
        except exceptions.TransportError as caught_exc:
            new_exc = exceptions.RefreshError(caught_exc)
            six.raise_from(new_exc, caught_exc)

        _, payload, _, _ = jwt._unverified_decode(id_token)
        return id_token, datetime.datetime.fromtimestamp(payload["exp"])
    def _update_token(self, request):
        """Updates credentials with a new access_token representing
        the downscoped credentials.

        Args:
            request (google.auth.transport.requests.Request): Request object
                to use for refreshing credentials.
        """

        # Refresh our source credentials.
        self._source_credentials.refresh(request)

        request = google.auth.transport.requests.Request()

        ac = AnonymousCredentials()
        authed_session = AuthorizedSession(credentials=ac)

        body = {
            "grant_type": 'urn:ietf:params:oauth:grant-type:token-exchange',
            "subject_token_type":
            'urn:ietf:params:oauth:token-type:access_token',
            "requested_token_type":
            'urn:ietf:params:oauth:token-type:access_token',
            "subject_token": self._source_credentials.token,
            "options": json.dumps(self._downscoped_options)
        }

        resp = authed_session.post(_STS_ENDPOINT, data=body)
        if resp.status_code != http_client.OK:
            raise exceptions.RefreshError(_REFRESH_ERROR)

        data = resp.json()
        self.token = data['access_token']

        if 'expires_in' in data:
            self.expiry = datetime.now() + \
                timedelta(seconds=int(data['expires_in']))
        else:
            authed_session = AuthorizedSession(credentials=ac)
            payload = {'access_token': self._source_credentials.token}
            token_response = authed_session.get(_TOKEN_INFO_ENDPOINT,
                                                params=payload)
            if token_response.status_code != http_client.OK:
                raise exceptions.RefreshError(_TOKEN_INFO_ERROR)
            tokeninfo_data = token_response.json()
            self.expiry = datetime.now() + \
                timedelta(seconds=int(tokeninfo_data['expires_in']))
def _make_iam_token_request(request, principal, headers, body):
    """Makes a request to the Google Cloud IAM service for an access token.
    Args:
        request (Request): The Request object to use.
        principal (str): The principal to request an access token for.
        headers (Mapping[str, str]): Map of headers to transmit.
        body (Mapping[str, str]): JSON Payload body for the iamcredentials
            API call.

    Raises:
        TransportError: Raised if there is an underlying HTTP connection
        Error
        DefaultCredentialsError: Raised if the impersonated credentials
        are not available.  Common reasons are
        `iamcredentials.googleapis.com` is not enabled or the
        `Service Account Token Creator` is not assigned
    """
    iam_endpoint = _IAM_ENDPOINT.format(principal)

    body = json.dumps(body)

    response = request(
        url=iam_endpoint,
        method='POST',
        headers=headers,
        body=body)

    response_body = response.data.decode('utf-8')

    if response.status != http_client.OK:
        exceptions.RefreshError(_REFRESH_ERROR, response_body)

    try:
        token_response = json.loads(response.data.decode('utf-8'))
        token = token_response['accessToken']
        expiry = datetime.strptime(
            token_response['expireTime'], '%Y-%m-%dT%H:%M:%SZ')

        return token, expiry

    except (KeyError, ValueError) as caught_exc:
        new_exc = exceptions.RefreshError(
            '{}: No access token or invalid expiration in response.'.format(
                _REFRESH_ERROR),
            response_body)
        six.raise_from(new_exc, caught_exc)
 def refresh(self, request):
     if self._raise_error:
         raise exceptions.RefreshError(
             "Failed to refresh access token in source credentials.")
     now = _helpers.utcnow()
     self._counter += 1
     self.token = "ACCESS_TOKEN_{}".format(self._counter)
     self.expiry = now + datetime.timedelta(seconds=self._expires_in)
Beispiel #19
0
def refresh_grant(request,
                  token_uri,
                  refresh_token,
                  client_id,
                  client_secret,
                  scopes=None):
    """Implements the OAuth 2.0 refresh token grant.

    For more details, see `rfc678 section 6`_.

    Args:
        request (google.auth.transport.Request): A callable used to make
            HTTP requests.
        token_uri (str): The OAuth 2.0 authorizations server's token endpoint
            URI.
        refresh_token (str): The refresh token to use to get a new access
            token.
        client_id (str): The OAuth 2.0 application's client ID.
        client_secret (str): The Oauth 2.0 appliaction's client secret.
        scopes (Optional(Sequence[str])): Scopes to request. If present, all
            scopes must be authorized for the refresh token. Useful if refresh
            token has a wild card scope (e.g.
            'https://www.googleapis.com/auth/any-api').

    Returns:
        Tuple[str, Optional[str], Optional[datetime], Mapping[str, str]]: The
            access token, new refresh token, expiration, and additional data
            returned by the token endpoint.

    Raises:
        google.auth.exceptions.RefreshError: If the token endpoint returned
            an error.

    .. _rfc6748 section 6: https://tools.ietf.org/html/rfc6749#section-6
    """
    body = {
        'grant_type': _REFRESH_GRANT_TYPE,
        'client_id': client_id,
        'client_secret': client_secret,
        'refresh_token': refresh_token,
    }
    if scopes:
        body['scope'] = ' '.join(scopes)

    response_data = _token_endpoint_request(request, token_uri, body)

    try:
        access_token = response_data['access_token']
    except KeyError as caught_exc:
        new_exc = exceptions.RefreshError('No access token in response.',
                                          response_data)
        six.raise_from(new_exc, caught_exc)

    refresh_token = response_data.get('refresh_token', refresh_token)
    expiry = _parse_expiry(response_data)

    return access_token, refresh_token, expiry, response_data
Beispiel #20
0
 def testTokenRefreshDeniedByCAAError(self):
     refresh_mock = self.StartObjectPatch(credentials.Credentials,
                                          'before_request')
     refresh_mock.side_effect = google_auth_exceptions.RefreshError(
         'access_denied: Account restricted')
     http_client = creds_requests.GetSession()
     with self.assertRaisesRegex(
             store.TokenRefreshDeniedByCAAError,
             'Access was blocked due to an organization policy'):
         http_client.request('GET', 'http://foo.com')
Beispiel #21
0
    def _get_region(self, request, url):
        """Retrieves the current AWS region from either the AWS_REGION or
        AWS_DEFAULT_REGION environment variable or from the AWS metadata server.

        Args:
            request (google.auth.transport.Request): A callable used to make
                HTTP requests.
            url (str): The AWS metadata server region URL.

        Returns:
            str: The current AWS region.

        Raises:
            google.auth.exceptions.RefreshError: If an error occurs while
                retrieving the AWS region.
        """
        # The AWS metadata server is not available in some AWS environments
        # such as AWS lambda. Instead, it is available via environment
        # variable.
        env_aws_region = os.environ.get(environment_vars.AWS_REGION)
        if env_aws_region is not None:
            return env_aws_region

        env_aws_region = os.environ.get(environment_vars.AWS_DEFAULT_REGION)
        if env_aws_region is not None:
            return env_aws_region

        if not self._region_url:
            raise exceptions.RefreshError("Unable to determine AWS region")
        response = request(url=self._region_url, method="GET")

        # Support both string and bytes type response.data.
        response_body = (response.data.decode("utf-8") if hasattr(
            response.data, "decode") else response.data)

        if response.status != 200:
            raise exceptions.RefreshError("Unable to retrieve AWS region",
                                          response_body)

        # This endpoint will return the region in format: us-east-2b.
        # Only the us-east-2 part should be used.
        return response_body[:-1]
Beispiel #22
0
 def _parse_token_data(self,
                       token_content,
                       format_type="text",
                       subject_token_field_name=None):
     content, filename = token_content
     if format_type == "text":
         token = content
     else:
         try:
             # Parse file content as JSON.
             response_data = json.loads(content)
             # Get the subject_token.
             token = response_data[subject_token_field_name]
         except (KeyError, ValueError):
             raise exceptions.RefreshError(
                 "Unable to parse subject_token from JSON file '{}' using key '{}'"
                 .format(filename, subject_token_field_name))
     if not token:
         raise exceptions.RefreshError(
             "Missing subject_token in the credential_source file")
     return token
Beispiel #23
0
 def testBatchTokenRefreshDeniedByCAAErrorGoogleAuth(self):
     refresh_mock = self.StartObjectPatch(credentials.Credentials,
                                          'before_request')
     refresh_mock.side_effect = google_auth_exceptions.RefreshError(
         'access_denied: Account restricted')
     http_client = http.Http(use_google_auth=True)
     batch_http_request = batch.BatchHttpRequest(
         'https://www.googleapis.com/batch/compute')
     with self.assertRaisesRegex(
             store.TokenRefreshDeniedByCAAError,
             'Access was blocked due to an organization policy'):
         batch_http_request.Execute(http_client)
Beispiel #24
0
    def _get_url_data(self, request, url, headers):
        response = request(url=url, method="GET", headers=headers)

        # support both string and bytes type response.data
        response_body = (response.data.decode("utf-8") if hasattr(
            response.data, "decode") else response.data)

        if response.status != 200:
            raise exceptions.RefreshError(
                "Unable to retrieve Identity Pool subject token",
                response_body)

        return response_body, url
Beispiel #25
0
    def _initialize_impersonated_credentials(self):
        """Generates an impersonated credentials.

        For more details, see `projects.serviceAccounts.generateAccessToken`_.

        .. _projects.serviceAccounts.generateAccessToken: https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/generateAccessToken

        Returns:
            impersonated_credentials.Credential: The impersonated credentials
                object.

        Raises:
            google.auth.exceptions.RefreshError: If the generateAccessToken
                endpoint returned an error.
        """
        # Return copy of instance with no service account impersonation.
        source_credentials = self.__class__(
            audience=self._audience,
            subject_token_type=self._subject_token_type,
            token_url=self._token_url,
            credential_source=self._credential_source,
            service_account_impersonation_url=None,
            client_id=self._client_id,
            client_secret=self._client_secret,
            quota_project_id=self._quota_project_id,
            scopes=self._scopes,
            default_scopes=self._default_scopes,
        )

        # Determine target_principal.
        start_index = self._service_account_impersonation_url.rfind("/")
        end_index = self._service_account_impersonation_url.find(
            ":generateAccessToken")
        if start_index != -1 and end_index != -1 and start_index < end_index:
            start_index = start_index + 1
            target_principal = self._service_account_impersonation_url[
                start_index:end_index]
        else:
            raise exceptions.RefreshError(
                "Unable to determine target principal from service account impersonation URL."
            )

        scopes = self._scopes if self._scopes is not None else self._default_scopes
        # Initialize and return impersonated credentials.
        return impersonated_credentials.Credentials(
            source_credentials=source_credentials,
            target_principal=target_principal,
            target_scopes=scopes,
            quota_project_id=self._quota_project_id,
            iam_endpoint_override=self._service_account_impersonation_url,
        )
Beispiel #26
0
    def refresh(self, request):
        """Raises an exception, these credentials can not be directly
        refreshed.

        Args:
            request (Any): Unused.

        Raises:
            google.auth.RefreshError
        """
        # pylint: disable=unused-argument
        # (pylint doesn't correctly recognize overridden methods.)
        raise exceptions.RefreshError(
            'OnDemandCredentials can not be directly refreshed.')
Beispiel #27
0
    def _initialize_impersonated_credentials(self):
        """Generates an impersonated credentials.

        For more details, see `projects.serviceAccounts.generateAccessToken`_.

        .. _projects.serviceAccounts.generateAccessToken: https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/generateAccessToken

        Returns:
            impersonated_credentials.Credential: The impersonated credentials
                object.

        Raises:
            google.auth.exceptions.RefreshError: If the generateAccessToken
                endpoint returned an error.
        """
        # Return copy of instance with no service account impersonation.
        d = dict(
            audience=self._audience,
            subject_token_type=self._subject_token_type,
            token_url=self._token_url,
            credential_source=self._credential_source,
            service_account_impersonation_url=None,
            client_id=self._client_id,
            client_secret=self._client_secret,
            quota_project_id=self._quota_project_id,
            scopes=self._scopes,
            default_scopes=self._default_scopes,
            workforce_pool_user_project=self._workforce_pool_user_project,
        )
        if not self.is_workforce_pool:
            d.pop("workforce_pool_user_project")
        source_credentials = self.__class__(**d)

        # Determine target_principal.
        target_principal = self.service_account_email
        if not target_principal:
            raise exceptions.RefreshError(
                "Unable to determine target principal from service account impersonation URL."
            )

        scopes = self._scopes if self._scopes is not None else self._default_scopes
        # Initialize and return impersonated credentials.
        return impersonated_credentials.Credentials(
            source_credentials=source_credentials,
            target_principal=target_principal,
            target_scopes=scopes,
            quota_project_id=self._quota_project_id,
            iam_endpoint_override=self._service_account_impersonation_url,
        )
  def refresh(self, request):
    if (self._refresh_token is None or self._token_uri is None or
        self._client_id is None or self._client_secret is None):
      raise exceptions.RefreshError(
          'The credentials do not contain the necessary fields need to '
          'refresh the access token. You must specify refresh_token, '
          'token_uri, client_id, and client_secret.')

    access_token, refresh_token, expiry, grant_response = (
        _client.refresh_grant(request, self._token_uri, self._refresh_token,
                              self._client_id, self._client_secret))

    self.token = access_token
    self.expiry = expiry
    self._refresh_token = refresh_token
    self._id_token = grant_response.get('id_token')
Beispiel #29
0
def _handle_error_response(response_data):
    """Translates an error response into an exception.

    Args:
        response_data (Mapping): The decoded response data.

    Raises:
        google.auth.exceptions.RefreshError: The errors contained in response_data.
    """
    try:
        error_details = "{}: {}".format(response_data["error"],
                                        response_data.get("error_description"))
    # If no details could be extracted, use the response data.
    except (KeyError, ValueError):
        error_details = json.dumps(response_data)

    raise exceptions.RefreshError(error_details, response_data)
Beispiel #30
0
async def refresh_grant(session: ClientSession, token_uri, refresh_token,
                        client_id, client_secret):
    """Implements the OAuth 2.0 refresh token grant.

    For more details, see `rfc678 section 6`_.

    Args:
        request (google.auth.transport.Request): A callable used to make
            HTTP requests.
        token_uri (str): The OAuth 2.0 authorizations server's token endpoint
            URI.
        refresh_token (str): The refresh token to use to get a new access
            token.
        client_id (str): The OAuth 2.0 application's client ID.
        client_secret (str): The Oauth 2.0 appliaction's client secret.

    Returns:
        Tuple[str, Optional[str], Optional[datetime], Mapping[str, str]]: The
            access token, new refresh token, expiration, and additional data
            returned by the token endpoint.

    Raises:
        google.auth.exceptions.RefreshError: If the token endpoint returned
            an error.

    .. _rfc6748 section 6: https://tools.ietf.org/html/rfc6749#section-6
    """
    body = {
        'grant_type': _REFRESH_GRANT_TYPE,
        'client_id': client_id,
        'client_secret': client_secret,
        'refresh_token': refresh_token,
    }

    response_data = await _token_endpoint_request(session, token_uri, body)

    try:
        access_token = response_data['access_token']
    except KeyError:
        raise exceptions.RefreshError('No access token in response.',
                                      response_data)

    refresh_token = response_data.get('refresh_token', refresh_token)
    expiry = _parse_expiry(response_data)

    return access_token, refresh_token, expiry, response_data