Registry

The registry is specifically designed to store supported algorithms, allowed algorithms, registered header parameters, and provides methods to validate algorithms and headers.

Note

We’ll use JWSRegistry as our reference, but keep in mind that the behavior of JWERegistry is identical.

Algorithms

The JWSRegistry or JWERegistry serves as a storage for all supported algorithms in JWS or JWE. By default, it enforces the usage of recommended algorithms, ensuring a higher level of security.

Find all the supported and recommended algorithms in:

You have the flexibility to create a custom registry tailored to your specific program requirements, allowing you to define and restrict the algorithms used. For instance, you can design a custom JWS registry that only permits the usage of RS256 and ES256 algorithms. This ensures that only these specific algorithms are allowed in your program.

from joserfc.jws import JWSRegistry

registry = JWSRegistry(algorithms=["RS256", "ES256"])
# jws.serialize_compact(protected, payload, key, registry=registry)

An example of a custom JWE registry that only permits the usage of {"alg": "A128KW", "enc": "A128GCM"}:

from joserfc.jwe import JWERegistry

registry = JWERegistry(algorithms=["A128KW", "A128GCM"])
# jwe.encrypt_compact(protected, payload, key, registry=registry)

Headers

By default, the JWSRegistry only permits the usage of registered header parameters. Additionally, it verifies the validity of the header parameter values before allowing their usage.

Type checking

The header parameter registry for JWS and JWE performs an initial check on the value type.

>>> from joserfc import jws
>>> jws.serialize_compact({"alg": "HS256", "kid": 123}, "hello", "secret")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "$/joserfc/jws.py", line 98, in serialize_compact
    registry.check_header(protected)
  File "$/joserfc/rfc7515/registry.py", line 63, in check_header
    validate_registry_header(self.header_registry, header)
  File "$/joserfc/registry.py", line 193, in validate_registry_header
    raise ValueError(f'"{key}" in header {error}')
ValueError: "kid" in header must be a str

In the above example, kid MUST be a string instead of an integer. The default registry validates the kid before processing the serialization.

Critical headers

There is a special “crit” header parameter for JWS and JWE, which specifies the critical header parameters. These critical parameters are considered mandatory, indicating that they must be present. For example:

>>> from joserfc import jws
>>> jws.serialize_compact({"alg": "HS256", "crit": ["kid"]}, "hello", "secret")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "$/joserfc/jws.py", line 98, in serialize_compact
    registry.check_header(protected)
  File "$/joserfc/rfc7515/registry.py", line 62, in check_header
    check_crit_header(header)
  File "$/joserfc/registry.py", line 195, in check_crit_header
    raise ValueError(f'"{k}" is a critical header')
ValueError: "kid" is a critical header

Since “kid” is listed as a critical (crit) header parameter, it is mandatory and must be included in the header.

Additional headers

By default, the registry for JWS and JWE only permits registered header parameters. Any additional header beyond those supported by the algorithm will result in an error.

>>> from joserfc import jws
>>> jws.serialize_compact({"alg": "HS256", "custom": "hi"}, "hello", "secret")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/lepture/authlib/joserfc/src/joserfc/jws.py", line 98, in serialize_compact
    registry.check_header(protected)
  File "/home/lepture/authlib/joserfc/src/joserfc/rfc7515/registry.py", line 65, in check_header
    check_supported_header(self.header_registry, header)
  File "/home/lepture/authlib/joserfc/src/joserfc/registry.py", line 175, in check_supported_header
    raise ValueError(f'Unsupported "{unsupported_keys} in header')
ValueError: Unsupported {'custom'} in header

To resolve this error, you have two options. First, you can register the additional header parameters with the registry. This allows the registry to recognize and validate those parameters instead of raising an error.

from joserfc import jws
from joserfc.jws import JWSRegistry
from joserfc.registry import HeaderParameter

additional_header_registry = {
    "custom": HeaderParameter("Custom message", "str", required=True),
}
registry = JWSRegistry(additional_header_registry)

# it will not raise any error
jws.serialize_compact({"alg": "HS256", "custom": "hi"}, "hello", "secret", registry=registry)

# this will raise an error, because we "custom" is defined to be required
jws.serialize_compact({"alg": "HS256"}, "hello", "secret", registry=registry)

Alternatively, you can choose to disable the strict header checking altogether. By turning off strict header checking, the registry will no longer raise an error for unrecognized header parameters. However, please note that this approach may compromise the security and integrity of the token, so it should be used with caution.

registry = JWSRegistry(strict_check_header=False)
# will not raise any error
jws.serialize_compact({"alg": "HS256", "custom": "hi"}, "hello", "secret", registry=registry)

Registry for JWT

JSON Web Token (JWT) is built on top of JSON Web Signature or JSON Web Encryption. The encode and decode methods accept a registry parameter. Depending on the algorithm of the JWT, you need to decide whether to use JWSRegistry or JWERegistry.