summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/index.rst41
-rw-r--r--itsdangerous.py27
-rw-r--r--setup.py5
-rw-r--r--tests.py5
4 files changed, 65 insertions, 13 deletions
diff --git a/docs/index.rst b/docs/index.rst
index daaabae..6edf202 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -13,12 +13,13 @@ Granted, the receiver can decode the contents and look into the package,
but they can not modify the contents unless they also have your secret
key. So if you keep the key secret and complex, you will be fine.
-Internally itsdangerous uses HMAC and SHA1 for signing and bases the
+Internally itsdangerous uses HMAC and SHA1 for signing by default and bases the
implementation on the `Django signing module
-<https://docs.djangoproject.com/en/dev/topics/signing/>`_. The library is
-BSD licensed and written by Armin Ronacher though most of the copyright
-for the design and implementation goes to Simon Willison and the other
-amazing Django people that made this library possible.
+<https://docs.djangoproject.com/en/dev/topics/signing/>`_. It also
+however supports JSON Web Signatures (JWS). The library is BSD licensed and
+written by Armin Ronacher though most of the copyright for the design and
+implementation goes to Simon Willison and the other amazing Django people
+that made this library possible.
Installation
------------
@@ -119,6 +120,36 @@ this, itsdangerous also provides URL safe serializers:
>>> s.loads('WzEsMiwzLDRd.wSPHqC0gR7VUqivlSukJ0IeTDgo')
[1, 2, 3, 4]
+JSON Web Signatures
+-------------------
+
+Starting with “itsdangerous” 0.18 JSON Web Signatures are also supported.
+They generally work very similar to the already existing URL safe
+serializer but will emit headers according to the current draft (10) of
+the JSON Web Signature (JWS) [``draft-ietf-jose-json-web-signature``].
+
+>>> from itsdangerous import JSONWebSignatureSerializer
+>>> s = JSONWebSignatureSerializer('secret-key')
+>>> s.dumps({'x': 42})
+'eyJhbGciOiJIUzI1NiJ9.eyJ4Ijo0Mn0.ZdTn1YyGz9Yx5B5wNpWRL221G1WpVE5fPCPKNuc6UAo'
+
+When loading the value back the header will not be returned by default
+like with the other serializers. However it is possible to also ask for
+the header by passing ``return_header=True``.
+Custom header fields can be provided upon serialization:
+
+>>> s.dumps(0, header_fields={'v': 1})
+'eyJhbGciOiJIUzI1NiIsInYiOjF9.MA.wT-RZI9YU06R919VBdAfTLn82_iIQD70J_j-3F4z_aM'
+>>> s.loads('eyJhbGciOiJIUzI1NiIsInYiOjF9.MA.wT-RZI9YU06R919VBdAf'
+... 'TLn82_iIQD70J_j-3F4z_aM', return_header=True)
+...
+(0, {u'alg': u'HS256', u'v': 1})
+
+“itsdangerous” only provides HMAC SHA derivatives and the none algorithm
+at the moment and does not support the ECC based ones. The algorithm in
+the header is checked against the one of the serializer and on a mismatch
+a :exc:`BadSignature` exception is raised.
+
.. _the-salt:
The Salt
diff --git a/itsdangerous.py b/itsdangerous.py
index 7b55a82..22c769e 100644
--- a/itsdangerous.py
+++ b/itsdangerous.py
@@ -494,22 +494,30 @@ class Serializer(object):
.. versionadded:: 0.15
"""
+ return self._loads_unsafe_impl(s, salt)
+
+ def _loads_unsafe_impl(self, s, salt, load_kwargs=None,
+ load_payload_kwargs=None):
+ """Lowlevel helper function to implement :meth:`loads_unsafe` in
+ serializer subclasses.
+ """
try:
- return True, self.loads(s, salt=salt)
+ return True, self.loads(s, salt=salt, **(load_kwargs or {}))
except BadSignature, e:
if e.payload is None:
return False, None
try:
- return False, self.load_payload(e.payload)
+ return False, self.load_payload(e.payload,
+ **(load_payload_kwargs or {}))
except BadPayload:
return False, None
- def load_unsafe(self, f, salt=None):
+ def load_unsafe(self, f, *args, **kwargs):
"""Like :meth:`loads_unsafe` but loads from a file.
.. versionadded:: 0.15
"""
- return self.loads_unsafe(f.read(), salt=salt)
+ return self.loads_unsafe(f.read(), *args, **kwargs)
class TimedSerializer(Serializer):
@@ -534,6 +542,11 @@ class TimedSerializer(Serializer):
return payload, timestamp
return payload
+ def loads_unsafe(self, s, max_age=None, salt=None):
+ load_kwargs = {'max_age': max_age}
+ load_payload_kwargs = {}
+ return self._loads_unsafe_impl(s, salt, load_kwargs, load_payload_kwargs)
+
class JSONWebSignatureSerializer(Serializer):
"""This serializer implements JSON Web Signature (JWS) support. Only
@@ -618,12 +631,16 @@ class JSONWebSignatureSerializer(Serializer):
payload, header = self.load_payload(
self.make_signer(salt, self.algorithm).unsign(s),
return_header=True)
- if header.pop('alg', None) != self.algorithm_name:
+ if header.get('alg') != self.algorithm_name:
raise BadSignature('Algorithm mismatch')
if return_header:
return payload, header
return payload
+ def loads_unsafe(self, s, salt=None, return_header=False):
+ kwargs = {'return_header': return_header}
+ return self._loads_unsafe_impl(s, salt, kwargs, kwargs)
+
class URLSafeSerializerMixin(object):
"""Mixed in with a regular serializer it will attempt to zlib compress
diff --git a/setup.py b/setup.py
index 17532b3..a7e8da0 100644
--- a/setup.py
+++ b/setup.py
@@ -8,10 +8,11 @@ setup(
name='itsdangerous',
author='Armin Ronacher',
author_email='armin.ronacher@active-4.com',
- version='0.17',
+ version='0.18',
url='http://github.com/mitsuhiko/itsdangerous',
py_modules=['itsdangerous'],
- description='Various helpers to pass trusted data to untrusted environments.',
+ description='Various helpers to pass trusted data to '
+ 'untrusted environments and back.',
zip_safe=False,
classifiers=[
'License :: OSI Approved :: BSD License',
diff --git a/tests.py b/tests.py
index 271d1b9..e719f5c 100644
--- a/tests.py
+++ b/tests.py
@@ -158,10 +158,13 @@ class JSONWebSignatureSerializerTestCase(SerializerTestCase):
header = {"typ": "dummy"}
s = self.make_serializer(secret_key)
+ full_header = header.copy()
+ full_header['alg'] = s.algorithm_name
+
ts = s.dumps(value, header_fields=header)
loaded, loaded_header = s.loads(ts, return_header=True)
self.assertEqual(loaded, value)
- self.assertEqual(loaded_header, header)
+ self.assertEqual(loaded_header, full_header)
def test_hmac_algorithms(self):
secret_key = 'predictable-key'