Skip to content

PyJWT

PyJWT is a Python library which allows you to encode and decode JSON Web Tokens (JWT). JWT is an open, industry-standard (RFC 7519) for representing claims securely between two parties.

Encoding & Decoding Tokens with HS256

>>> import jwt
>>> key = "secret"
>>> encoded = jwt.encode({"some": "payload"}, key, algorithm="HS256")
>>> print(encoded)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg
>>> jwt.decode(encoded, key, algorithms="HS256")
{'some': 'payload'}

Encoding & Decoding Tokens with RS256 (RSA)

>>> import jwt
>>> private_key = b"-----BEGIN PRIVATE KEY-----\nMIGEAgEAMBAGByqGSM49AgEGBS..."
>>> public_key = b"-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEAC..."
>>> encoded = jwt.encode({"some": "payload"}, private_key, algorithm="RS256")
>>> print(encoded)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg
>>> decoded = jwt.decode(encoded, public_key, algorithms=["RS256"])
{'some': 'payload'}

개인 키에 암호가 필요한 경우에서 PrivateKey객체 를 전달해야합니다 cryptography.

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

pem_bytes = b"-----BEGIN PRIVATE KEY-----\nMIGEAgEAMBAGByqGSM49AgEGBS..."
passphrase = b"your password"

private_key = serialization.load_pem_private_key(
    pem_bytes, password=passphrase, backend=default_backend()
)
encoded = jwt.encode({"some": "payload"}, private_key, algorithm="RS256")

추가 헤더 지정

>>> jwt.encode(
...     {"some": "payload"},
...     "secret",
...     algorithm="HS256",
...     headers={"kid": "230498151c214b788dd97f22b85410a5"},
... )
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjIzMDQ5ODE1MWMyMTRiNzg4ZGQ5N2YyMmI4NTQxMGE1In0.eyJzb21lIjoicGF5bG9hZCJ9.DogbDGmMHgA_bU05TAB-R6geQ2nMU2BRM-LnYEtefwg'

유효성 검사없이 클레임 세트 읽기

>>> jwt.decode(encoded, options={"verify_signature": False})
{'some': 'payload'}

유효성 검사없이 헤더 읽기

>>> jwt.get_unverified_header(encoded)
{'alg': 'RS256', 'typ': 'JWT', 'kid': 'key-id-12345...'}

등록 된 클레임 이름

JWT 사양은 일부 등록 된 클레임 이름을 정의하고 사용 방법을 정의합니다. PyJWT는 다음과 같은 등록 된 클레임 이름을 지원합니다.

  • "exp"(만료 시간) 클레임
  • “nbf”(Not Before Time) 클레임
  • "iss"(발행자) 클레임
  • "aud"(청중) 주장
  • "iat"(발급 날짜) 클레임

만료 시간 청구 (exp)

"exp"(만료 시간) 클레임은 JWT가 처리를 위해 허용되지 않아야하는 만료 시간 또는 그 이후의 만료 시간을 식별합니다. "exp"클레임을 처리하려면 현재 날짜 / 시간이 "exp"클레임에 나열된 만료 날짜 / 시간 이전이어야합니다. 구현자는 클록 스큐를 설명하기 위해 일반적으로 몇 분 이내의 작은 여유 시간을 제공 할 수 있습니다. 값은 NumericDate 값을 포함하는 숫자 여야합니다. 이 주장의 사용은 선택 사항입니다.

만료 시간이 자동으로 확인 (jwt.decode) 및 제기 jwt.ExpiredSignatureError를 만료 시간이 지난 경우 :

try:
    jwt.decode("JWT_STRING", "secret", algorithms=["HS256"])
except jwt.ExpiredSignatureError:
    # Signature has expired
    ...

PyJWT는 만료 시간 정의의 여유 부분도 지원합니다. 즉, 과거이지만 멀지 않은 만료 시간을 확인할 수 있습니다. 예를 들어 생성 후 만료 시간이 30 초로 설정된 JWT 페이로드가 있지만 때때로 30 초 후에 처리한다는 것을 알고있는 경우 약간의 여유를 갖기 위해 여유 시간을 10 초로 설정할 수 있습니다.

jwt_payload = jwt.encode(
    {"exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=30)}, "secret"
)

time.sleep(32)

# JWT payload is now expired
# But with some leeway, it will still validate
jwt.decode(jwt_payload, "secret", leeway=10, algorithms=["HS256"])

Not Before Time 클레임 (nbf)

"nbf"(이전 아님) 클레임은 JWT가 처리를 위해 허용되지 않아야하는 시간을 식별합니다. "nbf"클레임을 처리하려면 현재 날짜 / 시간이 "nbf"클레임에 나열된 이전 날짜 / 시간 이후이거나 같아야합니다. 구현자는 클록 스큐를 설명하기 위해 일반적으로 몇 분 이내의 작은 여유 시간을 제공 할 수 있습니다. 값은 NumericDate 값을 포함하는 숫자 여야합니다. 이 주장의 사용은 선택 사항입니다.

NBF의 주장은 비슷하게 작동 특급 위의 주장.

jwt.encode({"nbf": 1371720939}, "secret")
jwt.encode({"nbf": datetime.utcnow()}, "secret")

발행자 청구 (iss)

"iss"(발급자) 클레임은 JWT를 발행 한 주체를 식별합니다. 이 클레임의 처리는 일반적으로 애플리케이션에 따라 다릅니다. "iss"값은 StringOrURI 값을 포함하는 대소 문자를 구분하는 문자열입니다. 이 주장의 사용은 선택 사항입니다.

payload = {"some": "payload", "iss": "urn:foo"}

token = jwt.encode(payload, "secret")
decoded = jwt.decode(token, "secret", issuer="urn:foo", algorithms=["HS256"])

발급자 클레임이 잘못된 경우 jwt.InvalidIssuerError 가 발생합니다.

청중 주장 (aud)

"aud"(청중) 클레임은 JWT가 대상으로하는 수신자를 식별합니다. JWT를 처리하려는 각 주체는 청중 클레임의 값으로 자신을 식별해야합니다. 클레임을 처리하는 주체가이 클레임이있을 때 "aud"클레임의 값으로 자신을 식별하지 않으면 JWT를 거부해야합니다.

일반적으로 "aud"값은 각각 StringOrURI 값을 포함하는 대소 문자를 구분하는 문자열의 배열입니다.

payload = {"some": "payload", "aud": ["urn:foo", "urn:bar"]}

token = jwt.encode(payload, "secret")
decoded = jwt.decode(token, "secret", audience="urn:foo", algorithms=["HS256"])

여러 대상이 허용되는 경우 audience매개 변수 jwt.decode는 반복 가능할 수도 있습니다.

payload = {"some": "payload", "aud": "urn:foo"}

token = jwt.encode(payload, "secret")
decoded = jwt.decode(
    token, "secret", audience=["urn:foo", "urn:bar"], algorithms=["HS256"]
)

청중 클레임이 잘못된 경우 jwt.InvalidAudienceError 가 발생합니다.

청구시 발행 (iat)

iat (issued at) 클레임은 JWT가 발행 된 시간을 식별합니다. 이 클레임은 JWT의 나이를 결정하는 데 사용할 수 있습니다. 값은 NumericDate 값을 포함하는 숫자 여야합니다. 이 주장의 사용은 선택 사항입니다.

jwt.encode({"iat": 1371720939}, "secret")
jwt.encode({"iat": datetime.utcnow()}, "secret")

경우 IAT 주장은 숫자가 아닌, jwt.InvalidIssuedAtError의 예외가 발생합니다.

클레임 존재 요구

클레임 집합에 하나 이상의 클레임을 요구하려는 경우 require이러한 클레임을 포함 하도록 매개 변수를 설정할 수 있습니다 .

>>> jwt.decode(encoded, options={"require": ["exp", "iss", "sub"]})
{'exp': 1371720939, 'iss': 'urn:foo', 'sub': '25c37522-f148-4cbf-8ee6-c4a9718dd0af'}

JWKS 엔드 포인트에서 RSA 서명 키 검색

>>> import jwt
>>> from jwt import PyJWKClient
>>> token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik5FRTFRVVJCT1RNNE16STVSa0ZETlRZeE9UVTFNRGcyT0Rnd1EwVXpNVGsxUWpZeVJrUkZRdyJ9.eyJpc3MiOiJodHRwczovL2Rldi04N2V2eDlydS5hdXRoMC5jb20vIiwic3ViIjoiYVc0Q2NhNzl4UmVMV1V6MGFFMkg2a0QwTzNjWEJWdENAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vZXhwZW5zZXMtYXBpIiwiaWF0IjoxNTcyMDA2OTU0LCJleHAiOjE1NzIwMDY5NjQsImF6cCI6ImFXNENjYTc5eFJlTFdVejBhRTJINmtEME8zY1hCVnRDIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.PUxE7xn52aTCohGiWoSdMBZGiYAHwE5FYie0Y1qUT68IHSTXwXVd6hn02HTah6epvHHVKA2FqcFZ4GGv5VTHEvYpeggiiZMgbxFrmTEY0csL6VNkX1eaJGcuehwQCRBKRLL3zKmA5IKGy5GeUnIbpPHLHDxr-GXvgFzsdsyWlVQvPX2xjeaQ217r2PtxDeqjlf66UYl6oY6AqNS8DH3iryCvIfCcybRZkc_hdy-6ZMoKT6Piijvk_aXdm7-QQqKJFHLuEqrVSOuBqqiNfVrG27QzAPuPOxvfXTVLXL2jek5meH6n-VWgrBdoMFH93QEszEDowDAEhQPHVs0xj7SIzA"
>>> kid = "NEE1QURBOTM4MzI5RkFDNTYxOTU1MDg2ODgwQ0UzMTk1QjYyRkRFQw"
>>> url = "https://dev-87evx9ru.auth0.com/.well-known/jwks.json"
>>> jwks_client = PyJWKClient(url)
>>> signing_key = jwks_client.get_signing_key_from_jwt(token)
>>> data = jwt.decode(
...     token,
...     signing_key.key,
...     algorithms=["RS256"],
...     audience="https://expenses-api",
...     options={"verify_exp": False},
... )
>>> print(data)
{'iss': 'https://dev-87evx9ru.auth0.com/', 'sub': 'aW4Cca79xReLWUz0aE2H6kD0O3cXBVtC@clients', 'aud': 'https://expenses-api', 'iat': 1572006954, 'exp': 1572006964, 'azp': 'aW4Cca79xReLWUz0aE2H6kD0O3cXBVtC', 'gty': 'client-credentials'}

See also

Favorite site