Understanding JWT: Secure Token-Based Authentication for Modern Apps
This article explains the evolution from traditional cookie‑session authentication to token‑based JWT, detailing its structure, security mechanisms, implementation steps, advantages, limitations, and practical Java code examples, while also comparing it with modern authentication challenges in web and mobile environments.
Traditional Authentication Methods
In a typical e‑commerce scenario a user registers, logs in with a username and password, and then enjoys a long period without re‑entering credentials. Early web applications used the Cookie‑Session method:
User submits username/password or SMS code.
Server validates credentials, creates a Session, stores the SessionID in a cookie, and returns it to the browser.
Subsequent requests automatically include the cookie; the server retrieves the Session to verify the user.
This approach works for web browsers but faces problems for mobile apps, cross‑domain requests, distributed services, and CSRF attacks.
Improved Cookie‑Session (Hybrid) Approach
To address the issues, the workflow can be modified:
User logs in with credentials or SMS code.
Server validates and stores authentication data in Redis, returning a key to the client.
Client saves the key in local storage (or a local database on mobile).
For subsequent requests the client sends the key in a header or request body.
Server retrieves the authentication data from Redis using the key.
Diagrams illustrate the first‑login and subsequent‑login processes.
JWT Enters the Scene
JSON Web Token (JWT) implements the above hybrid idea: the token contains all necessary information, is signed, and can be verified without server‑side state.
JWT Data Structure
A JWT consists of three Base64‑URL‑encoded parts separated by dots:
Header – specifies token type and signing algorithm.
Payload – carries claims such as user data and standard fields.
Signature – computed over the header and payload.
Example header (JSON):
{
"alg": "HS256",
"typ": "JWT"
}Example payload (JSON):
{
"name": "Ancient Kite",
"introduce": "Handsome and elegant"
}Standard claim fields include iss (issuer), exp (expiration), sub (subject), aud (audience), nbf (not before), iat (issued at), and jti (JWT ID).
Signature Calculation
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secretKey
)The server keeps the secret key and verifies the signature using the same algorithm.
How to Use JWT
During login, the server validates credentials and returns a signed JWT.
The client stores the JWT in a cookie or localStorage.
For protected requests the client includes the JWT in the Authorization header (e.g., Bearer <token>) or in the request body.
The server recomputes the signature and, if it matches, trusts the request.
Diagrams show the request flow with JWT.
Ensuring Security
The security relies on the strength of the HMAC algorithm (e.g., HS256) and the secrecy of the server‑side key. Because the signature changes if any payload data is altered, tampering is detected. Transport security (HTTPS) prevents token interception, and reasonable expiration times limit exposure.
Limitations
Once issued, a JWT cannot be revoked before its expiration, which complicates scenarios such as forcing logout of previous sessions or limiting concurrent logins. Server‑side logic must be added to handle token revocation or rotation.
Common JWT Libraries (Java Example)
Popular Java libraries include java-jwt. Example Maven dependency:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>Creating a token:
public static String create() {
try {
Algorithm algorithm = Algorithm.HMAC256("secret");
String token = JWT.create()
.withIssuer("auth0")
.withSubject("subject")
.withClaim("name", "Ancient Kite")
.withClaim("introduce", "Handsome and elegant")
.sign(algorithm);
System.out.println(token);
return token;
} catch (JWTCreationException exception) {
throw exception;
}
}Verifying a token:
public static Boolean verify(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256("secret");
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("auth0")
.build();
DecodedJWT jwt = verifier.verify(token);
System.out.println(jwt.getPayload());
return true;
} catch (JWTVerificationException exception) {
return false;
}
}Running the example:
public static void main(String[] args) {
String token = create();
Boolean result = verify(token);
System.out.println(result);
}The output shows a valid token string and a verification result of true. Modifying the payload breaks verification and throws JWTVerificationException.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
