Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to check for JWT expiration without checking the signature? #600

Open
dolfinus opened this issue Dec 6, 2023 · 0 comments
Open

How to check for JWT expiration without checking the signature? #600

dolfinus opened this issue Dec 6, 2023 · 0 comments

Comments

@dolfinus
Copy link

dolfinus commented Dec 6, 2023

Hi.

I'm using authlib in Python client for a REST API implementing OAuth 2.0. Usage is simple as:

my_python_client = MyPythonClient(url="http://domain.com/api", token="some.jwt.token")
my_python_client.whoami()

Method whoami sends request to backend. It is using authlib.integrations.requests_client.OAuth2Session to wrap all auth interaction:

session = OAuth2Session()
session.token = AuthlibToken.from_dict(
    {
        "access_token": self.token,
        "token_type": "Bearer",
    },
)

session.request(self.url, ...)

Backend decodes this token and uses payload to get user data.

But if token is expired, I only get 401 error from backend indicating that token is invalid. This is not very good in terms if UX/DX.

How can I check that token is expired or malformed before it will be send to backend? To both show user a proper message on client side, and to raise exception of specific type (e.g. TokenExpiredError) which can be handled by developer.

Also without passing AuthlibToken.from_dict({"expires_at": ...}) authlib cannot detect that token is expired and another token should be issued instead (if using refresh_token, client_credentials and so on to automatically issue new access_token after expiration).

Currently the only way I could implement this is using python-jose:

token_decoded = jwt.decode(self.token, key="NONE", options={"verify_signature": False})
session.token = AuthlibToken.from_dict(
    {
        "access_token": self.token,
        "token_type": "Bearer",
        "expires_at": token_decoded["exp"],
    },
)

jwt.decode raises an exception jose.exceptions.ExpiredSignatureError: Signature has expired. Passing "verify_signature": False allows to decode token without checking its signature (which client cannot know in this case, secret key is private and used by backend only).

I've tried to use:

from authlib.jose.rfc7519.jwt import JsonWebToken
jwt = JsonWebToken(algorithms=None)

jwt.deserialize(token, key="")

or

from authlib.jose.rfc7515.jws import JsonWebSignature

signature = JsonWebSignature(algorithms=)
signature.deserialize(token, key="")

But they both raise authlib.jose.errors.BadSignatureError: bad_signature: because I didn't provide corresponding secret key to validate signature (which is intentional).

I also cannot pass algorithms=["NONE"] to any of those classes constructor to use key=None because real algorithm is determined using token content, and if it is not present in algorithms list an exception is raised authlib.jose.errors.UnsupportedAlgorithmError: unsupported_algorithm:.

So is there any way to check if token is expired without checking the signature?

@dolfinus dolfinus changed the title How to check for JWT expiration without checking the signature How to check for JWT expiration without checking the signature? Dec 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant