JWT Authentication Guide in Python

Written By mvishwakarma (Administrator)

Updated at September 10th, 2025

1. Overview

This document provides a detailed explanation of how to generate a Client Access Token for authenticating Annex Cloud public API calls.
The token is a JSON Web Token (JWT) signed using the HMAC-SHA256 algorithm to ensure:

  • Data integrity – the request cannot be altered without detection.
  • Authentication – confirming the request comes from a trusted client.

This guide covers:

  • JWT structure and components
  • How to generate the HMAC value for both POST/PATCH and GET requests
  • Step-by-step Python implementation example
  • Required HTTP headers when calling Annex Cloud APIs
 Library used -  jwt·PyPI

2. Understanding JWT

A JWT consists of three parts, each Base64URL-encoded and separated by a period (.):

<base64url-encoded header>.<base64url-encoded payload>.<base64url-encoded signature> 

2.1. JWT Components

a. Header

Defines the type of token and the signing algorithm used.

{ 
  "alg": "HS256", 
  "typ": "JWT" 
} 
  • alg: Signing algorithm (HS256 = HMAC with SHA-256)
  • typ: Token type (JWT)

b. Payload

Contains claims and authentication-related data.

Mandatory claims:

  • sub – Client identifier (shared during integration)
  • exp – Expiration time (in Unix timestamp seconds; ensures the token is valid only for a set duration)
  • site_id – Your Annex Cloud site ID
  • hmac – Base64-encoded HMAC-SHA256 signature of either:
    • The request JSON payload (POST/PATCH requests), or
    • The query parameter value (GET requests)

Example Payload:

{ 
  "sub": "socialannextestsite", 
  "exp": 1568674228, 
  "site_id": "yoursiteid", 
  "hmac": "generated_hmac_here" 
} 

c. Signature

The JWT signature is created as follows:

HMACSHA256( base64url(header) + "." + base64url(payload), shared_secret ) 

Where:

  • base64url(header) - Base64URL-encoded JSON header
  • base64url(payload) - Base64URL-encoded JSON payload
  • shared_secret - Your Annex Cloud shared secret key

3. HMAC Generation Rules

For POST / PATCH Requests

  1. Take the exact JSON payload you will send in the API request.
  2. Base64-encode the payload (standard Base64, not Base64URL).
  3. Generate the HMAC using SHA-256 with your shared secret key.
  4. Base64-encode the HMAC output.
  5. Insert this Base64-encoded HMAC into the hmac field in the JWT payload.

For GET Requests

  1. Take the query parameter value you will send.
  2. Convert it to JSON format (enclose it in quotes).
  3. Base64-encode this JSON string.
  4. Generate the HMAC using SHA-256 with your shared secret key.
  5. Base64-encode the HMAC output.
  6. Insert this Base64-encoded HMAC into the hmac field in the JWT payload.

Important: The payload or parameter used to generate the HMAC must exactly match what is sent in the API request. Even a single space difference will cause authentication failure.

4. Python Implementation Example

import json
import base64
import hmac
import hashlib
import jwt
import time
def generate_jwt_token(payload_json, key, site_id, site_name):
    """
    Generates a JWT token and HMAC from the given payload.
    :param payload_json: Dictionary containing payload data
    :param key: Secret key for HMAC and JWT signing
    :param site_id: Site ID to include in the JWT payload
    :param site_name: Site name to include in the JWT payload
    :return: JWT token as a string
    """
    # Convert the payload to a compact JSON string
    compact_json = json.dumps(payload_json, separators=(",", ":"))
    # Base64 encode the payload
    payload_base64 = base64.b64encode(compact_json.encode()).decode()
    # Generate HMAC
    hmac_value = base64.b64encode(
        hmac.new(key.encode(), payload_base64.encode(), hashlib.sha256).digest()
    ).decode()
    # Generate the JWT token
    token_data = {
        "sub": site_name,
        "exp": int(time.time()) + 86400000,  # Expiration time (10 days from now)
        "site_id": site_id,
        "hmac": hmac_value
    }
    jwt_token = jwt.encode(token_data, key, algorithm="HS256")
    return jwt_token

5. Required HTTP Headers for API Calls

When sending requests to Annex Cloud APIs, you must include the following headers:

Header Name

 

Value

 

Description

 

Authorization

Bearer <JWT_access_token>

The JWT generated using the above process

X-AnnexCloud-Site

<site_id>

Your Annex Cloud site ID

Content-Type

application/json

Request body format

Example
POST /api/3.0/points HTTP/1.1 
Authorization: Bearer eyJhbGciOiJIUzI1NiIs... 
X-AnnexCloud-Site: yoursiteid 
Content-Type: application/json