Skip to main content

Async library to fetch JWKs for JWT tokens

Project description

pyjwt-key-fetcher

GitHub Workflow Status Code style: black PyPI PyPI - Python Version License: BSD 3-Clause

Async library to fetch JWKs for JWT tokens.

This library is intended to be used together with PyJWT to automatically verify keys signed by for example OpenID Connect providers. It retrieves the iss (issuer) and the kid (key ID) from the JWT, fetches the configuration, typically from .well-known/openid-configuration (can be overridden) from the issuer to find out the jwks_uri (or jwks_url) and fetches that to find the right key.

This should give similar ability to verify keys as for example https://jwt.io/, where you can just paste in a token, and it will automatically reach out and retrieve the key for you.

The AsyncKeyFetcher provided by this library acts as an improved async replacement for PyJWKClient.

Installation

The package is available on PyPI:

pip install pyjwt-key-fetcher

Usage

Example

import asyncio

import jwt

from pyjwt_key_fetcher import AsyncKeyFetcher


async def main():
    fetcher = AsyncKeyFetcher()
    # Token and options copied from
    # https://pyjwt.readthedocs.io/en/2.6.0/usage.html#retrieve-rsa-signing-keys-from-a-jwks-endpoint
    token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik5FRTFRVVJCT1RNNE16STVSa0ZETlRZeE9UVTFNRGcyT0Rnd1EwVXpNVGsxUWpZeVJrUkZRdyJ9.eyJpc3MiOiJodHRwczovL2Rldi04N2V2eDlydS5hdXRoMC5jb20vIiwic3ViIjoiYVc0Q2NhNzl4UmVMV1V6MGFFMkg2a0QwTzNjWEJWdENAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vZXhwZW5zZXMtYXBpIiwiaWF0IjoxNTcyMDA2OTU0LCJleHAiOjE1NzIwMDY5NjQsImF6cCI6ImFXNENjYTc5eFJlTFdVejBhRTJINmtEME8zY1hCVnRDIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.PUxE7xn52aTCohGiWoSdMBZGiYAHwE5FYie0Y1qUT68IHSTXwXVd6hn02HTah6epvHHVKA2FqcFZ4GGv5VTHEvYpeggiiZMgbxFrmTEY0csL6VNkX1eaJGcuehwQCRBKRLL3zKmA5IKGy5GeUnIbpPHLHDxr-GXvgFzsdsyWlVQvPX2xjeaQ217r2PtxDeqjlf66UYl6oY6AqNS8DH3iryCvIfCcybRZkc_hdy-6ZMoKT6Piijvk_aXdm7-QQqKJFHLuEqrVSOuBqqiNfVrG27QzAPuPOxvfXTVLXL2jek5meH6n-VWgrBdoMFH93QEszEDowDAEhQPHVs0xj7SIzA"
    key_entry = await fetcher.get_key(token)
    token = jwt.decode(
        jwt=token,
        options={"verify_exp": False},
        audience="https://expenses-api",
        **key_entry
    )
    print(token)


if __name__ == "__main__":
    asyncio.run(main())

Options

Limiting issuers

You can limit the issuers you allow fetching keys from by setting the valid_issuers when creating the AsyncKeyFetcher, like this:

AsyncKeyFetcher(valid_issuers=["https://example.com"])

Adjusting caching

The AsyncKeyFetcher will by default cache data for up to 32 different issuers with a TTL of 3600 seconds (1 hour) each. This means that in case of key-revocation, the key will be trusted for up to 1 hour after it was removed from the JWKs.

If a previously unseen kid for an already seen issuer is seen, it will trigger a re-fetch of the JWKs, provided they have not been fetched in the past 5 minutes, in order to rather quickly react to new keys being published.

The amount of issuers to cache data for, as well as the cache time for the data can be adjusted like this:

AsyncKeyFetcher(cache_maxsize=10, cache_ttl=2*60*60)

The minimum interval for checking for new keys can for now not be adjusted.

Loading configuration from a custom path

You can change from which path the configuration is loaded from the issuer (iss). By default, the configuration is assumed to be an OpenID Connect configuration and to be loaded from /.well-known/openid-configuration. As long as the configuration contains a jwks_uri or a jwks_url you can change the configuration to be loaded from a custom path.

You can override the config path when creating the AsyncKeyFetcher like this:

AsyncKeyFetcher(config_path="/.well-known/dataspace/party-configuration.json")

Using static configuration

If you use an issuer that does not provide a configuration (they are for example missing the /.well-known/openid-configuration), you can create a static configuration to use for that issuer instead and in it specify the jwks_uri (or jwks_url) like this:

AsyncKeyFetcher(
    static_issuer_config={
        "https://example.com": {
            "jwks_uri": "https://example.com/.well-known/jwks.json",
        },
    },
)

Using your own HTTP Client

The library ships with a DefaultHTTPClient that uses aiohttp for fetching the JSON data; the openid-configuration and the jwks. If you want, you can write your own custom client by inheriting from the HTTPClient. The only requirement is that it implements an async function to fetch JSON from a given URL and return it as a dictionary.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyjwt_key_fetcher-0.8.0.tar.gz (14.7 kB view details)

Uploaded Source

Built Distribution

pyjwt_key_fetcher-0.8.0-py3-none-any.whl (16.5 kB view details)

Uploaded Python 3

File details

Details for the file pyjwt_key_fetcher-0.8.0.tar.gz.

File metadata

  • Download URL: pyjwt_key_fetcher-0.8.0.tar.gz
  • Upload date:
  • Size: 14.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.9.19 Linux/6.5.0-1025-azure

File hashes

Hashes for pyjwt_key_fetcher-0.8.0.tar.gz
Algorithm Hash digest
SHA256 6a0f0a95d6503bece7faa436b9b9f5953219f22b6e245e9a1e51bfc9320b0148
MD5 8683767c0f33799aaf9553e75eb20ed0
BLAKE2b-256 957b7dc0e72b66a5b2ea742618841ae3b2c2e73ecf8a269946a5a720314d059e

See more details on using hashes here.

File details

Details for the file pyjwt_key_fetcher-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: pyjwt_key_fetcher-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 16.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.9.19 Linux/6.5.0-1025-azure

File hashes

Hashes for pyjwt_key_fetcher-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9eba3e1c9d30592c076f069be32572c24816464b591965bdd3d61d1ca5fd7dc3
MD5 3fb856466eb9f8f09acb008a3f861c18
BLAKE2b-256 287b415c527e790a64319fb6525ea55e97e0cccb181f66c0d1381f36f78d402b

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page