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

encode()/decode() key parameter type should not be str #602

Closed
WolfgangFellger opened this issue Jan 11, 2021 · 6 comments · Fixed by #843 or #873
Closed

encode()/decode() key parameter type should not be str #602

WolfgangFellger opened this issue Jan 11, 2021 · 6 comments · Fixed by #843 or #873
Labels
stale Issues without activity for more than 60 days

Comments

@WolfgangFellger
Copy link

The jwt.encode() and jwt.decode() functions declare parameter key to be str. This seems to have been the case for a while, but with new release mypy will now complain that
Argument "key" has incompatible type "bytes"; expected "str" [arg-type]
when this parameter is given a bytes object.

Giving it a string does not seem to make sense though, the key is inherently binary (and indeed the first thing HMAC does is throw the key into force_bytes: https://github.com/jpadilla/pyjwt/blob/fdfd6871/jwt/algorithms.py#L173-174).

Everything works as intended when you pass in bytes, it's just the type declaration.

Expected Result

Parameter should accept bytes (and possibly not accept str)

Actual Result

mypy reports a type error when using bytes.
When using str it is impossible to pass random bits (since it will be run through .encode('utf-8'))

Reproduction Steps

import secrets
import jwt

secret = secrets.token_bytes(32)
token = jwt.encode(payload={"aud": "foobar"}, key=secret, algorithm="HS256")
result = jwt.decode(
    token,
    key=secret,
    audience="foobar",
    verify=True,
    algorithms=["HS256"],
    options={"require": ["aud"]},
)

Runs fine, but mypy will report errors.

@asthasr
Copy link

asthasr commented Feb 24, 2021

It should also accept the private key types from Cryptography (on encode) and the public key types (on decode).

Example:

import jwt
from cryptography.hazmat.primitives.asymmetric import rsa

private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096)
public_key = private_key.public_key()
encoded = jwt.encode({"foo": "bar"}, key=private_key, algorithm="RS256")
decoded = jwt.decode(encoded, key=public_key, algorithms=["RS256"])

@WolfgangFellger
Copy link
Author

Yeah, was discussed over in the PR. Seems like the only practical solution at this time is going to Any.

@prryplatypus
Copy link

prryplatypus commented Apr 7, 2022

Hi there! I know this issue is kinda old, but thought I'd chip in to say that the jwt.api_jwt.decode_complete method would probably also need this fixed :)

EDIT: Looks like this was changed in the PR already, sorry! Hoping it gets merged soon :D

@github-actions
Copy link

github-actions bot commented Jun 7, 2022

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

@github-actions github-actions bot added the stale Issues without activity for more than 60 days label Jun 7, 2022
@ps-george
Copy link

This still seems to be an issue

michael-k added a commit to michael-k/pyjwt that referenced this issue Jun 20, 2022
@Viicos
Copy link
Contributor

Viicos commented Dec 26, 2022

The proper way to do it would be to use generics, and would require two TypeVar, one for the key parameter of the prepare_key method, and another one for the key parameter of the sign method (which is the same type as the return value of prepare_key).

I'm currently writing a solution, and will make a PR, we'll be able to see if this is a reliable solution.

Edit: After a quick look, generics are not the only reliable option

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale Issues without activity for more than 60 days
Projects
None yet
5 participants