1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
Migrating from python-jose
==========================
``python-jose`` supports all JOSE specifications, similar to ``joserfc``.
However, there are significant differences in code structure, method names,
and parameter usage. Additionally, ``joserfc`` offers built-in Python type
hints, enhancing code readability and type safety.
Another key difference is that ``python-jose`` only supports compact serialization
and deserialization, whereas ``joserfc`` supports both compact and JSON serialization
formats, offering greater flexibility in handling JOSE data.
JWS
---
In ``python-jose``, the methods used for serialization and deserialization are
``jws.sign`` and ``jws.verify``, respectively.
On the other hand, ``joserfc`` uses ``jws.serialize_compact`` for serialization
and ``jws.deserialize_compact`` for deserialization.
.. code-block:: python
:caption: python-jose
from jose import jws
signed = jws.sign({'a': 'b'}, 'your-secret-key', algorithm='HS256')
jws.verify(signed, 'your-secret-key', algorithms='HS256')
# the verify only returns the payload
.. code-block:: python
:caption: joserfc
import json
from joserfc import jws
from joserfc.jwk import OctKey
key = OctKey.import_key("your-secret-key")
protected = {"alg": "HS256"}
signed = jws.serialize_compact(protected, json.dumps({'a': 'b'}), key)
obj = jws.deserialize_compact(text, key)
# access the payload with obj.payload
.. important::
``joserfc`` is designed to be highly explicit, requiring the use of specific
key types, payload formats, and other components. For example, in the previous
example, we explicitly use an OctKey instead of a simple string. Additionally,
since JWS in joserfc only supports encoding strings and bytes, you cannot pass
a dictionary directly as the payload. Instead, the payload must first be converted
to a JSON string using json.dumps. This explicit approach ensures better type
safety and clarity in your code.
JWE
---
In ``python-jose``, the methods used for encryption and decryption are ``jwe.encrypt``
and ``jwe.decrypt``. However, since ``joserfc`` supports both compact and JSON serialization
formats, it provides distinct methods: ``jwe.encrypt_compact`` and ``jwe.decrypt_compact`` for
compact serialization, ensuring clear differentiation between the formats and greater
flexibility in handling JWE operations.
.. code-block:: python
:caption: python-jose
from jose import jwe
encrypted = jwe.encrypt('Hello, World!', 'asecret128bitkey', algorithm='dir', encryption='A128GCM')
jwe.decrypt(encrypted, 'asecret128bitkey')
# => 'Hello, World!'
.. code-block:: python
:caption: joserfc
from joserfc import jwe
from joserfc.jwk import OctKey
key = OctKey.generate_key(128) # 128bit key
protected = {'alg': 'dir', 'enc': 'A128GCM'}
encrypted = jwe.encrypt_compact(protected, 'Hello, World!', key)
obj = jwe.decrypt_compact(encrypted, key)
# obj.payload => b'Hello, World!'
JWT
---
The ``jwt`` module in ``python-jose`` supports only JWS (JSON Web Signature) mode,
whereas ``joserfc`` provides support for both JWS and JWE (JSON Web Encryption) modes.
Although both libraries utilize the ``encode`` and ``decode`` methods, their parameters
differ significantly in terms of structure and flexibility.
.. code-block:: python
:caption: python-jose
from jose import jwt
encoded = jwt.encode({'a': 'b'}, 'your-secret-key', algorithm='HS256')
jwt.decode(encoded, 'your-secret-key', algorithms='HS256')
# => {'a': 'b'}
.. code-block:: python
:caption: joserfc
from joserfc import jwt
from joserfc.jwk import OctKey
key = OctKey.import_key("your-secret-key")
# jwt.encode(header, payload, key)
encoded = jwt.encode({"alg": "HS256"}, {'a': 'b'}, key)
token = jwt.decode(encoded, key)
# => token.header : {"alg": "HS256"}
# => token.claims : {"a": "b"}
``get_unverified_header``
~~~~~~~~~~~~~~~~~~~~~~~~~
The ``jwt`` module in python-jose provides a method called ``get_unverified_header``,
which allows extracting the header from a JWT without verifying its signature.
In ``joserfc``, we can get the unverified header with:
.. code-block:: python
:caption: joserfc
from typing import Any
from joserfc import jws
def get_unverified_header(token: str) -> dict[str, Any]:
obj = jws.extract_compact(token.encode())
return obj.protected
``get_unverified_claims``
~~~~~~~~~~~~~~~~~~~~~~~~~
You can also use the ``jws.extract_compact`` method to extract the JWT's claims:
.. code-block:: python
:caption: joserfc
import json
from typing import Any
from joserfc import jws
def get_unverified_claims(token: str) -> dict[str, Any]:
obj = jws.extract_compact(token.encode())
return json.loads(obj.payload)
JWK
---
In ``python-jose``, you can use ``jwk.construct`` to create a key instance
from a JWK-formatted dictionary. In contrast, ``joserfc`` provides the
``jwk.import_key`` method to achieve the same result.
.. code-block:: python
:caption: joserfc
from joserfc import jwk
jwk.import_key({
"kty": "oct",
"kid": "018c0ae5-4d9b-471b-bfd6-eef314bc7037",
"use": "sig",
"alg": "HS256",
"k": "hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg"
})
|