Exemple #1
0
    def _make_jwt_for_audience(self, audience):
        """Make a new JWT for the given audience.

        Args:
            audience (str): The intended audience.

        Returns:
            Tuple[bytes, datetime]: The encoded JWT and the expiration.
        """
        now = _helpers.utcnow()
        lifetime = datetime.timedelta(seconds=self._token_lifetime)
        expiry = now + lifetime

        payload = {
            'iss': self._issuer,
            'sub': self._subject,
            'iat': _helpers.datetime_to_secs(now),
            'exp': _helpers.datetime_to_secs(expiry),
            'aud': audience,
        }

        payload.update(self._additional_claims)

        jwt = encode(self._signer, payload)

        return jwt, expiry
Exemple #2
0
def _verify_iat_and_exp(payload):
    """Verifies the ``iat`` (Issued At) and ``exp`` (Expires) claims in a token
    payload.

    Args:
        payload (Mapping[str, str]): The JWT payload.

    Raises:
        ValueError: if any checks failed.
    """
    now = _helpers.datetime_to_secs(_helpers.utcnow())

    # Make sure the iat and exp claims are present.
    for key in ('iat', 'exp'):
        if key not in payload:
            raise ValueError(
                'Token does not contain required claim {}'.format(key))

    # Make sure the token wasn't issued in the future.
    iat = payload['iat']
    # Err on the side of accepting a token that is slightly early to account
    # for clock skew.
    earliest = iat - _helpers.CLOCK_SKEW_SECS
    if now < earliest:
        raise ValueError('Token used too early, {} < {}'.format(now, iat))

    # Make sure the token wasn't issued in the past.
    exp = payload['exp']
    # Err on the side of accepting a token that is slightly out of date
    # to account for clow skew.
    latest = exp + _helpers.CLOCK_SKEW_SECS
    if latest < now:
        raise ValueError('Token expired, {} < {}'.format(latest, now))
Exemple #3
0
    def _make_authorization_grant_assertion(self):
        """Create the OAuth 2.0 assertion.

        This assertion is used during the OAuth 2.0 grant to acquire an
        access token.

        Returns:
            bytes: The authorization grant assertion.
        """
        now = _helpers.utcnow()
        lifetime = datetime.timedelta(seconds=_DEFAULT_TOKEN_LIFETIME_SECS)
        expiry = now + lifetime

        payload = {
            'iat': _helpers.datetime_to_secs(now),
            'exp': _helpers.datetime_to_secs(expiry),
            # The issuer must be the service account email.
            'iss': self._service_account_email,
            # The audience must be the auth token endpoint's URI
            'aud': self._token_uri,
            'scope': _helpers.scopes_to_string(self._scopes or ())
        }

        payload.update(self._additional_claims)

        # The subject can be a user email for domain-wide delegation.
        if self._subject:
            payload.setdefault('sub', self._subject)

        token = jwt.encode(self._signer, payload)

        return token
Exemple #4
0
    def expired(self):
        """Checks if the credentials are expired.

        Note that credentials can be invalid but not expired becaue Credentials
        with :attr:`expiry` set to None is considered to never expire.
        """
        if not self.expiry:
            return False

        # Remove 5 minutes from expiry to err on the side of reporting
        # expiration early so that we avoid the 401-refresh-retry loop.
        skewed_expiry = self.expiry - _helpers.CLOCK_SKEW
        return _helpers.utcnow() >= skewed_expiry
Exemple #5
0
def _parse_expiry(response_data):
    """Parses the expiry field from a response into a datetime.

    Args:
        response_data (Mapping): The JSON-parsed response data.

    Returns:
        Optional[datetime]: The expiration or ``None`` if no expiration was
            specified.
    """
    expires_in = response_data.get('expires_in', None)

    if expires_in is not None:
        return _helpers.utcnow() + datetime.timedelta(seconds=expires_in)
    else:
        return None
Exemple #6
0
    def _get_jwt_for_audience(self, audience):
        """Get a JWT For a given audience.

        If there is already an existing, non-expired token in the cache for
        the audience, that token is used. Otherwise, a new token will be
        created.

        Args:
            audience (str): The intended audience.

        Returns:
            bytes: The encoded JWT.
        """
        token, expiry = self._cache.get(audience, (None, None))

        if token is None or expiry < _helpers.utcnow():
            token, expiry = self._make_jwt_for_audience(audience)
            self._cache[audience] = token, expiry

        return token