def make_refresh_authorization_grant_assertion(token_info: TokenInfo, service_accout: ServiceAccount): """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 = 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': service_accout.credentials.service_account_email, # The audience must be the auth token endpoint's URI 'aud': token_info.aud, 'scope': token_info.scope, } # The subject can be a user email for domain-wide delegation. payload.setdefault('sub', token_info.uid) token = jwt.encode(service_accout.credentials._signer, payload) return token
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
def _make_jwt(self, audience=None): """Make a signed JWT. Args: audience (str): Overrides the instance's current audience claim. 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 or self._issuer, 'iat': _helpers.datetime_to_secs(now), 'exp': _helpers.datetime_to_secs(expiry), 'aud': audience or self._audience, } payload.update(self._additional_claims) jwt = encode(self._signer, payload) return jwt, expiry
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 ID 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, # The target audience specifies which service the ID token is # intended for. "target_audience": self._target_audience, } payload.update(self._additional_claims) token = jwt.encode(self._signer, payload) return token
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
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 ID 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, # The target audience specifies which service the ID token is # intended for. 'target_audience': self._target_audience } payload.update(self._additional_claims) token = jwt.encode(self._signer, payload) return token
def test_decode_success_with_custom_clock_skew(token_factory): token = token_factory( claims={ "exp": _helpers.datetime_to_secs(_helpers.utcnow() + datetime.timedelta(seconds=2)), "iat": _helpers.datetime_to_secs(_helpers.utcnow() - datetime.timedelta(seconds=2)), }) jwt.decode(token, PUBLIC_CERT_BYTES, clock_skew_in_seconds=1)
async def test_id_token_jwt_grant(): now = _helpers.utcnow() id_token_expiry = _helpers.datetime_to_secs(now) id_token = jwt.encode(test_client.SIGNER, { "exp": id_token_expiry }).decode("utf-8") request = make_request({"id_token": id_token, "extra": "data"}) token, expiry, extra_data = await _client.id_token_jwt_grant( request, "http://example.com", "assertion_value") # Check request call verify_request_params( request, { "grant_type": sync_client._JWT_GRANT_TYPE, "assertion": "assertion_value" }, ) # Check result assert token == id_token # JWT does not store microseconds now = now.replace(microsecond=0) assert expiry == now assert extra_data["extra"] == "data"
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'] earliest = iat - _CLOCK_SKEW_SECS if now < earliest: raise ValueError('Token used too early, {} < {}'.format(now, iat)) # Make sure the token wasn't issue in the past exp = payload['exp'] latest = exp + _CLOCK_SKEW_SECS if latest < now: raise ValueError('Token expired, {} < {}'.format(latest, now))
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))
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))
def test_decode_bad_token_too_early(token_factory): token = token_factory(claims={ 'iat': _helpers.datetime_to_secs( _helpers.utcnow() + datetime.timedelta(hours=1)) }) with pytest.raises(ValueError) as excinfo: jwt.decode(token, PUBLIC_CERT_BYTES) assert excinfo.match(r'Token used too early')
def test_decode_bad_token_expired(token_factory): token = token_factory(claims={ 'exp': _helpers.datetime_to_secs( _helpers.utcnow() - datetime.timedelta(hours=1)) }) with pytest.raises(ValueError) as excinfo: jwt.decode(token, PUBLIC_CERT_BYTES) assert excinfo.match(r'Token expired')
def _make_jwt_for_audience(self): """ Make a JSON Web Token given a service file :rtype: string :returns: signed authentication """ now = _helpers.utcnow() lifetime = timedelta(seconds=_TOKEN_EXPIRATION) self._token_expiration = now + lifetime payload = { 'aud': self._token_uri, 'iss': self._signer_email, 'iat': _helpers.datetime_to_secs(now), 'exp': _helpers.datetime_to_secs(self._token_expiration), 'scope' : self._scopes } return encode(self._signer, payload) # from google.auth.jwt.encode
def _make_jwt(self): """Make a signed JWT. 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": self._audience, } payload.update(self._additional_claims) jwt = encode(self._signer, payload) return jwt, expiry
def factory(claims=None, key_id=None): now = _helpers.datetime_to_secs(_helpers.utcnow()) payload = { 'aud': '*****@*****.**', 'iat': now, 'exp': now + 300, 'user': '******', 'metadata': {'meta': 'data'} } payload.update(claims or {}) # False is specified to remove the signer's key id for testing # headers without key ids. if key_id is False: signer.key_id = None key_id = None return jwt.encode(signer, payload, key_id=key_id)
def factory(claims=None, key_id=None): now = _helpers.datetime_to_secs(_helpers.utcnow()) payload = { "aud": "*****@*****.**", "iat": now, "exp": now + 300, "user": "******", "metadata": { "meta": "data" }, } payload.update(claims or {}) # False is specified to remove the signer's key id for testing # headers without key ids. if key_id is False: signer._key_id = None key_id = None return jwt.encode(signer, payload, key_id=key_id)
def test_id_token_jwt_grant(): now = _helpers.utcnow() id_token_expiry = _helpers.datetime_to_secs(now) id_token = jwt.encode(SIGNER, {'exp': id_token_expiry}).decode('utf-8') request = make_request({'id_token': id_token, 'extra': 'data'}) token, expiry, extra_data = _client.id_token_jwt_grant( request, 'http://example.com', 'assertion_value') # Check request call verify_request_params(request, { 'grant_type': _client._JWT_GRANT_TYPE, 'assertion': 'assertion_value' }) # Check result assert token == id_token # JWT does not store microseconds now = now.replace(microsecond=0) assert expiry == now assert extra_data['extra'] == 'data'
def test_datetime_to_secs(): assert _helpers.datetime_to_secs(datetime.datetime(1970, 1, 1)) == 0 assert _helpers.datetime_to_secs(datetime.datetime(1990, 5, 29)) == 643939200