JWT Decode Python
Python's PyJWT package makes it possible to encrypt and decrypt JSON Web Tokens (JWT). JWT is a public, recognized global benchmark for safely expressing demands between two parties (RFC 7519).
JSON Web Token (JWT)
A JSON web token (JWT) is a JSON object that is used to transmit information safely over the internet. It could be utilized for information sharing as well as an authentication method. Tokens are primarily made up of a header, payload, and signature. There are dots between these three sections (.).
JWT specifies the data format that we are passing from one side to the other and offers Scripted and Discripted formats. Data is primarily sent via the web for each request and response using the serialized technique. While reading and writing information on the internet, token uses the deserialized method.
Deserialized
JWT just has the heading and the payload when it is deserialized. They are both simple JSON objects.
Header
The most common application of a header in a JWT is to explain the cryptographic functions carried out on it, such as the signature and decryption methods. Additionally, it could include details about the format and message of the information we are transmitting.
This data is presented as a JSON object, which is subsequently encoded to a BASE64URL. If the JWT is signed/unsigned or encoded, the cryptographic processes in the header determine what algorithm approaches to employ. The code below depicts how a JWT's basic header might appear:
{
"typ":"JWT",
"alg":"HS256"
}
The object variables "alg" and "typ" both have various values and distinct purposes. For example, "typ" informs us what kind of header this entitles has, but "alg" provides information on the encoding technique employed.
The two primary algorithms we employ in the header area of a JWT do seem to be HS256 and RS256.
There are several JWTs that may be generated without encoding or verification. Any such token is known as insecure, and the result of the alg object key supplied to it in its header must be "none."
{
"alg": "none"
}
Payload
The JWT's payload is where the entirety of the consumer data is really inserted. The "claims" of the JWT are another name for this information. It is usually advisable not to enter any personal data in this place as anyone may view this data. User data is usually included in this section.
This data is presented as a JSON object, which is subsequently converted to a BASE64URL. A payload can contain quite as many promises as we desire, whereas a header, a payload, does not require any promises. The JWT with that of the payload will resemble the following:
{
"userId":"b07f85be-45da",
"iss": "https://provider.domain.com/",
"sub": "auth/some-hash-here",
"exp": 153452683
}
UserId, iss, sub, and exp can be found in the JWT in question. All of them have various functions since userId is the user ID that we are saving, iss informs us of the issuer, sub denotes the topic, and exp denotes the expiry date.
Serialized
JWT denotes a string with the prescribed sequence when it is serialized:
[header].[payload].[signature]
The serialized JWT is made up of these three parts. The definitions and purposes of the header and payload are well known. Let's discuss signatures.
Signature
This, the third component of JWT, is employed to confirm the legitimacy of the token. The payload and header of a BASE64URL are connected by a dot (.), as well as the payload is therefore hashed utilizing a private key and the hashing method specified in the header. The real credential header is created by appending this identity by using a dot (.) character to the header and payload. Payload.signature
Syntax:
HASHINGALGO( base64UrlEncode(header) + “.” + base64UrlEncode(payload),secret)
A JWT is therefore made up of all the aforementioned elements in combination. Let's examine how our real token will resemble:
JWT Example:
Header:
{
"alg" : "HS256",
"typ" : "JWT"
}
Payload:
{
"id": 123456789,
"name": "Joseph"
}
Specifying Additional Headers
>>>jwt.encode(
...
{"some": "payload"},
...
"secret",
...
algorithm="HS256",
...
headers={"kid": "230498151c214b788dd97f22b85410a5"},
... )
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjIzMDQ5ODE1MWMyMTRiNzg4ZGQ5N2YyMmI4NTQxMGE1In0.eyJzb21lIjoicGF5bG9hZCJ9.DogbDGmMHgA_bU05TAB-R6geQ2nMU2BRM-LnYEtefwg'
Reading the Claims without Validation
Setting the validation identity feature to False will allow you to view the claims of a JWT instead of validating the signature or any of the listed claim names.
NOTE: Until you are certain of your actions, it is typically not advisable to utilize this capability. The trustworthiness or validity of the claim set cannot be guaranteed in the absence of biometric authentication information.
>>>jwt.decode(encoded, options={"verify_signature": False})
{'some': 'payload'}
Reading Headers without Validation
A JWT header must sometimes be viewed without being validated by an API. The token provider might put a key id in the header, for instance, if they employ numerous keys while you have no way to determine beforehand which of their private secrets or public keys to utilize for verification.
>>>jwt.get_unverified_header(encoded)
{'alg': 'RS256', 'typ': 'JWT', 'kid': 'key-id-12345...'}
Registered Claim Names
Several authorized claim names are defined in the JWT standard, as well as their appropriate usage. Several authorized claim names are supported by PyJWT:
- "exp" (Expiration Time) Claim
- "nbf" (Not Before Time) Claim
- "iss" (Issuer) Claim
- "aud" (Audience) Claim
- "iat" (Issued At) Claim
Expiration Time Claim (exp)
The JWT should not be allowed for execution after the expiration period specified in the "exp" (expiration time) claims. The present date and time should be earlier than the expiry date and time specified in the "exp" claim in order to handle the "exp" claim. Professional developers MAY allow for a very short amount of time to accommodate for clock skew, often no more than a few mins. It must include a value that is a number with a NumericDate value. This statement use is OPTIONAL.
The expiry time can be given either as a datetime or as a data type that will be transformed into a UTC UNIX timestamp. For instance:
jwt.encode({"exp": 1371720939}, "secret")
jwt.encode({"exp": datetime.now(tz=timezone.utc)}, "secret")
In jwt.decode(), the expiry date is dynamically validated and raised. If the expiry time has passed, an ExpiredSignatureError will occur:
Try:
jwt.decode("JWT_STRING", "secret", algorithms=["HS256"])
except for jwt.ExpiredSignatureError:
# Signature has expired
...
Utilize a UTC date stamp or date-time when encrypting since the expiry date will be relative to the current UTC time (as indicated by timegm(datetime.now(tz=timezone.utc).utctimetuple())).
Including the choices arguments verify exp field, you may disable expiry time verification.
The leeway portion of the expiry time description is also supported by PyJWT, allowing you to verify a termination date that is in the previous but not too far away. For instance, if a JWT payload's expiry period is set to 30 seconds following issuance, but you are aware that occasionally you will execute it later than that time, you may specify a leeway of 10 seconds to provide a small buffer:
jwt_payload = jwt.encode(
{"exp": datetime.datetime.now(tz=timezone.utc) + 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"])
A datetime. timedelta example can be utilized as the leeway rather than a couple of seconds. In the above example, the final sentence is equal to:
jwt. decode(
jwt_payload, "secret", leeway=datetime.timedelta(seconds=10), algorithms=
["HS256"]
)
Not before Time Claim (nbf)
The "nbf" (not before) claims indicate when the JWT should not be considered for execution. The present date and time Should be afterwards or equivalent to the not-before-date and time are given in the "nbf" claim in order to be processed the "nbf" claim. Reference implementation MAY allow for a very short amount of time to accommodate for clock skew, often no more than another few minutes. It MUST have a value that is a number with NumericDate values. This claim's use is Additional service.
The bf claim operates similarly to the aforementioned exp claim.
jwt.encode({"nbf": 1371720939}, "secret")
jwt.encode({"nbf": datetime.now(tz=timezone.utc)}, "secret")
Audience Claim (aud)
The receivers of the JWT are specified by the "aud" (audience) claim. Every principle that the JWT is designed to process should associate themselves with an integer in the client claim. The JWT Should refused if the primary executing the claim does not associate himself with values in the "aud" claim while this demand is present.
The "aud" result is often an array of particular instance strings, every of which contains a StringOrURI value.
payload = {"some": "payload", "aud": ["urn:foo", "urn:bar"]}
token = jwt.encode(payload, "secret")
decoded = jwt.decode(token, "secret", audience="urn:foo", algorithms=["HS256"])
The "aud" number could be a unique case-sensitive string holding a StringOrURI expression in the unique scenario where the JWT has a unique user.
payload = {"some": "payload", "aud": "urn:foo"}
token = jwt.encode(payload, "secret")
decoded = jwt.decode(token, "secret", audience="urn:foo", algorithms=["HS256"])
The viewer option for jwt.decode can also be effective in generating if numerous listeners are supported.
payload = {"some": "payload", "aud": "urn:foo"}
token = jwt.encode(payload, "secret")
decoded = jwt.decode(
token, "secret", audience=["urn:foo", "urn:bar"], algorithms=["HS256"]
)
Software interpretations of customer values are typical. This claim's use is OPTIONAL.
Jwt.InvalidAudienceError will be thrown if the crowd claim is false.