Python API Development with FastAPI
Advanced FastAPI
Jwt Token Basics
In this lesson, we explore one of the most critical aspects of API and application development: authentication. There are two primary methods to handle user authentication:
- Session-based authentication – A session is stored on the backend server (or API) to track whether a user is logged in. This session data is typically saved in memory or in a database and remains active until the user logs out.
- JWT token-based authentication – This stateless approach involves no backend storage for login sessions. Instead, the client stores a token containing all the necessary authentication details, and the API verifies this token to authenticate the user.
Stateless Authentication
JWT token-based authentication simplifies horizontal scaling and reduces backend storage needs since the client is responsible for holding the token.
When a user logs in successfully via JWT, the API generates a token that the client retains. Every time the client needs to access a protected resource (for example, hitting the /posts
endpoint), it sends the token in the request header. The API then validates the token to ensure the user is authenticated. The typical flow is as follows:
- The client sends credentials (usually an email and password) to a login endpoint (e.g.,
/login
). - The API validates the credentials and, if they are correct, generates a JWT token.
- The client stores this token and includes it in the header for all subsequent requests to protected resources.
- The API extracts and verifies the token. If the token is valid, the API responds with the requested data.
The API does not maintain any session state; token validation alone confirms that the user is authenticated.
JWT Token Structure
A JWT token is comprised of three parts separated by dots: the header, the payload, and the signature. Although the token is just a string, it carries structured data essential for authentication.
1. Header
The header contains metadata about the token, such as the token type and the algorithm used for signing. A typical header looks like this:
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload
The payload includes the actual data (claims) of the token. This can include non-sensitive information such as the user’s ID, name, or role. It is important to note that the payload is not encrypted, so sensitive data (like passwords) should never be stored here.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
You might also include additional metadata like user roles, but always keep the payload lightweight to reduce the overall token size.
3. Signature
The signature ensures the integrity of the token—it detects any tampering. To generate the signature, the API encodes the header and payload with a secret key (known only to the API) using a hashing algorithm (commonly HS256). In pseudocode, the process is as follows:
# Compute the signature for the token
signature = HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
your_256_bit_secret
)
Below is a consolidated example that outlines the JWT token generation process:
# Header
header = {
"alg": "HS256",
"typ": "JWT"
}
# Payload
payload = {
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
# Signature generation (pseudocode)
# The signature is generated by concatenating the base64Url encoded header and payload,
# separated by a period, and then hashing this string with a secret key.
# Example:
# HMACSHA256(
# base64UrlEncode(header) + "." + base64UrlEncode(payload),
# your_256_bit_secret
# )
The final JWT token is formed by concatenating the base64Url encoded header, payload, and signature with dots (.) used as separators.
Data Integrity and the Role of the Signature
It is essential to understand that a JWT is not encrypted; its data is merely encoded. This means anyone can decode the header and payload to read the information. However, the signature ensures that any tampering is detected. If a malicious user alters any part of the header or payload (for instance, changing their role from "user" to "admin"), the signature computed by the API using the secret key will not match, and the token will be rejected.
The token verification process works as follows:
- The API receives the token along with the client's request.
- It extracts the header and payload from the token and recomputes the signature using the secret key.
- If the recomputed signature matches the signature in the token, the token is considered valid.
- If the signatures do not match, the API rejects the token, ensuring that tampered tokens are not accepted.
Important Security Note
Always keep your secret key confidential. Exposure of this key compromises the integrity of your token-based system since attackers could generate valid tokens.
Summary
JWT token-based authentication provides a secure and stateless method for handling user authentication by:
- Accepting user credentials at login.
- Generating a token that includes a header, payload, and signature.
- Storing the token on the client side for use in future requests.
- Validating the token with every protected resource request using a secret key.
This approach not only simplifies backend architecture by eliminating the need for session storage but also enhances scalability across distributed systems.
For further reading, check out the following resources:
By mastering JWT token-based authentication, you ensure a secure and efficient method for user verification, keeping your API robust and scalable.
Watch Video
Watch video content