URL quote Fernet tokens
The padding in base64.urlsafe_b64encode()'s output is not actually URL safe, so you have to quote the result when it's of variable length. In addition, Fernet tokens can always be handled as bytes, despite being passed in from json.loads() as Unicode. Change-Id: I72dbd4ddc066706f6af6ea2f2bcd5f0a6cb9b30c Closes-Bug: 1433372 Closes-Bug: 1431669
This commit is contained in:
parent
a998ead704
commit
68a54c2cf1
|
@ -2402,7 +2402,7 @@ class FernetFederatedTokenTests(FederationTests, FederatedSetupMixin):
|
|||
|
||||
def test_federated_unscoped_token(self):
|
||||
resp = self._issue_unscoped_token()
|
||||
self.assertEqual(184, len(resp.headers['X-Subject-Token']))
|
||||
self.assertEqual(186, len(resp.headers['X-Subject-Token']))
|
||||
|
||||
def test_federated_unscoped_token_with_multiple_groups(self):
|
||||
assertion = 'ANOTHER_CUSTOMER_ASSERTION'
|
||||
|
|
|
@ -21,6 +21,7 @@ from oslo_config import cfg
|
|||
from oslo_log import log
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
from six.moves import urllib
|
||||
|
||||
from keystone.auth import plugins as auth_plugins
|
||||
from keystone import exception
|
||||
|
@ -64,19 +65,29 @@ class TokenFormatter(object):
|
|||
|
||||
def pack(self, payload):
|
||||
"""Pack a payload for transport as a token."""
|
||||
return self.crypto.encrypt(payload)
|
||||
# base64 padding (if any) is not URL-safe
|
||||
return urllib.parse.quote(self.crypto.encrypt(payload))
|
||||
|
||||
def unpack(self, token):
|
||||
"""Unpack a token, and validate the payload."""
|
||||
token = urllib.parse.unquote(six.binary_type(token))
|
||||
|
||||
try:
|
||||
return self.crypto.decrypt(token, ttl=CONF.token.expiration)
|
||||
return self.crypto.decrypt(token)
|
||||
except fernet.InvalidToken as e:
|
||||
raise exception.Unauthorized(six.text_type(e))
|
||||
|
||||
@classmethod
|
||||
def creation_time(cls, fernet_token):
|
||||
"""Returns the creation time of a valid Fernet token."""
|
||||
# fernet tokens are base64 encoded, so we need to unpack them first
|
||||
# tokens may be transmitted as Unicode, but they're just ASCII
|
||||
# (pypi/cryptography will refuse to operate on Unicode input)
|
||||
fernet_token = six.binary_type(fernet_token)
|
||||
|
||||
# the base64 padding on fernet tokens is made URL-safe
|
||||
fernet_token = urllib.parse.unquote(fernet_token)
|
||||
|
||||
# fernet tokens are base64 encoded and the padding made URL-safe
|
||||
token_bytes = base64.urlsafe_b64decode(fernet_token)
|
||||
|
||||
# slice into the byte array to get just the timestamp
|
||||
|
|
Loading…
Reference in New Issue