Python JWT introduction and use

JWT introduction

​ jwt (JSON Web Tokens) is a developed industry standard RFC 7519, which is used to securely express the statement between the two parties. At present, jwt is widely used in the user authentication of the system, especially in the front-end and back-end separation projects.

​jwt certification process:

In project development, authentication is generally performed according to the process shown in the figure above, that is: after the user logs in successfully, the server returns a token to the user browser, and the user browser needs to carry the token before sending a request to the server. Verify the legitimacy of the token, show the data to the user if it is legal, otherwise, return some error messages

What is the difference between traditional token method and jwt in terms of authentication?

Traditional token method

After the user logs in successfully, the server generates a random token to the user, and saves a token in the server (database or cache). Later, the user needs to carry the token when visiting again. After the server receives the token, it goes to the database or cache Check whether the token is timed out and legal

jwt way

After the user logs in successfully, the server generates a random token to the user through jwt (the server does not need to keep the token), and the user needs to carry the token when visiting again. After the server receives the token, the jwt verifies whether the token is timed out or not. legitimate

JWT create token

JWT generation principle

The format of the generated token of jwt is as follows, consisting of three strings connected by.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lI
iwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

The generation rules are as follows

  • The HEADER part of the first paragraph always contains the algorithm and token type, and base64url encrypts this json
{
"alg": "HS256",
"typ": "JWT"
}
  • The second paragraph PAYLOAD part contains some data, this json is base64url encrypted
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
...
}
  • In the SIGNATURE part of the third paragraph, the base64url ciphertext of the first two paragraphs is spliced together, and then HS256 is encrypted, and then the hs256 ciphertext is encrypted by base64url.
base64url(
	HMACSHA256(
		base64UrlEncode(header) + "." + base64UrlEncode(payload),
	your-256-bit-secret (Secret key plus salt)
	)
)

Finally, the three strings are joined by. To generate the jwt token

Note: base64url encryption is to do base64 encryption first, and then replace-with + and _ with /

Principle of JWT verification token

Generally, after the authentication is successful, the token generated by jwt is returned to the user, and the user needs to carry the token when accessing again in the future. At this time, jwt needs to perform a timeout and legality check on the token.

After obtaining the token, it will be verified according to the following steps

  • Split the token into three parts: header_segment, payload_segment, crypto_segment
JWT_TOKEN =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

signing_input, crypto_segment = JWT_TOKEN.rsplit('.', 1)
header_segment, payload_segment = signing_input.split('.', 1)
  • Decrypt the first part of header_segment with base64url to get the header
  • Decrypt the second part of payload_segment with base64url to get the payload
  • Decrypt the third part of crypto_segment with base64url to get the signature, and verify the validity of the signature part of the data
    • Splice the first two ciphertexts to get signing_input
    • Obtain the encryption algorithm from the first paragraph of plaintext, the default is HS256
    • Use algorithm + salt to encrypt signing_input, and compare the result with the signature ciphertext

Sample code

Create jwt token based on Python’s pyjwt module

Installation

pip3 install pyjwt

Example

from datetime import datetime, timedelta

import jwt


class JwtToken(object):

    _salt = "@^4_00wedv**pi)+(!w1rwi=d3q4l=ie=g-u$s8jevmj*zgg2h" 

    _expire_message = dict(code=1200, msg="token has expired")

    _unknown_error_message = dict(code=4200, msg="token parsing failed")

    @classmethod
    def generate_token(cls, payload: dict) -> str:
        headers = dict(typ="jwt", alg="HS256")
        resut = jwt.encode(payload=payload, key=cls._salt, algorithm="HS256", headers=headers)
        return resut

    @classmethod
    def parse_token(cls, token: str) -> tuple:
        verify_status = False
        try:
            payload_data = jwt.decode(token, cls._salt, algorithms=['HS256'])
            verify_status = True
        except jwt.ExpiredSignatureError:
            payload_data = cls._expire_message
        except Exception as _err:
            payload_data = cls._unknown_error_message
        return verify_status, payload_data


if __name__ == '__main__':
    TEST_DATA = dict(name="mooor", exp=datetime.utcnow() - timedelta(seconds=1))
    token = JwtToken.generate_token(TEST_DATA)
    print(token)
    payload = JwtToken.parse_token(token)
    print(payload)

Expiration time will be compared to the current UTC time (as given by timegm(datetime.utcnow().utctimetuple())), so be sure to use a UTC timestamp or datetime in encoding

Parameter introduction

Sample code

import jwt
import datetime

dic = {
    'exp': datetime.datetime.utcnow() + datetime.timedelta(days=1),  # expire date
    'iat': datetime.datetime.utcnow(),  #  Starting time
    'iss': 'ChaosMoor',                 #  signature
    'data': {                           #  Content, generally store the user id and start time
        'a': 1,
        'b': 2,
    },
}


token = jwt.encode(dic, 'secret', algorithm='HS256')                            # Encrypted string
print(token)

payload = jwt.decode(token, 'secret', issuer='lianzong', algorithms=['HS256'])  # Decrypt and verify signature
print(s)
print(type(s))

dic has an officially designated key, and the program will judge whether it is legal according to the value of the key when decrypting. These keys have

  • “exp”: When generating a token, you can set the validity time of the token. If we set an expiration of 1 day, we will throw out the token after we parse the token after 1 day
jwt.exceptions.ExpiredSignatureError: Signature has expired
  • “nbf”: It refers to the effective time of the token, if it is used but the effective time is not reached, it will be thrown
jwt.exceptions.ImmatureSignatureError: The token is not yet valid (nbf)
  • “iss”: The issuer of the token, we can give him a string. Note that there is no problem if is not checked when receiving, if we need to check when receiving but the signatures are inconsistent, it will be thrown
jwt.exceptions.InvalidIssuerError: Invalid issuer
  • “aud”: The receiver is specified. When receiving, the receiver must provide the receiver (string) that is consistent with the token requirement. If the receiver is not written or the receiver is inconsistent, it will be thrown
jwt.exceptions.InvalidAudienceError: Invalid audience
  • “iat”: the start time of the token, if the current time is before the start time, it will be thrown
jwt.exceptions.InvalidIssuedAtError: Issued At claim (iat) cannot be in the future.

Leave a Reply