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 사양은 일부 등록 된 클레임 이름을 정의하고 사용 방법을 정의합니다. 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의 주장은 비슷하게 작동 특급 위의 주장.
발행자 청구 (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 값을 포함하는 숫자 여야합니다. 이 주장의 사용은 선택 사항입니다.
경우 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'}