0Pricing
Java Academy · Lesson

JWT: Structure, Creation, and Verification

Manually decode JWT structure, create signed tokens with a secret, and verify claims without frameworks.

JWT: Structure, Creation, and Verification is a free Java Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is a JWT?

JSON Web Token (JWT) is a compact, URL-safe token format for transmitting claims between parties. A JWT is signed (and optionally encrypted). It is self-contained — no database lookup needed to verify claims.

JWT Structure: Header.Payload.Signature

A JWT has three Base64URL-encoded parts separated by dots: header.payload.signature. The header specifies the algorithm. The payload contains claims. The signature verifies integrity.

// Example JWT:
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9      <- header
// .eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0  <- payload
// .SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c     <- signature

Header and Payload Decoded

Decode each part with Base64URL to see the JSON. The payload contains "claims" — standard ones: sub (subject), iss (issuer), exp (expiration), iat (issued at).

// Header:
{ "alg": "HS256", "typ": "JWT" }
// Payload:
{ "sub": "user-42", "name": "Alice", "role": "ADMIN",
  "iat": 1716000000, "exp": 1716003600 }

Creating a JWT Manually (HS256)

Build header and payload JSON, Base64URL-encode each, concatenate with a dot, then compute HMAC-SHA256 of header.payload and append as the signature.

String header  = Base64.getUrlEncoder().withoutPadding()
    .encodeToString("{\"alg\":\"HS256\",\"typ\":\"JWT\"}".getBytes());
String payload = Base64.getUrlEncoder().withoutPadding()
    .encodeToString("{\"sub\":\"user-42\",\"exp\":9999999999}".getBytes());
String sigInput = header + "." + payload;
byte[] sig = computeHmac(secretKey, sigInput);
String jwt = sigInput + "." + Base64.getUrlEncoder().withoutPadding().encodeToString(sig);

Verifying a JWT Manually

Split on dots, decode header and payload, recompute HMAC over header.payload, compare to the signature, and check that exp is in the future.

String[] parts = jwt.split("\\.");
String sigInput = parts[0] + "." + parts[1];
byte[] expectedSig = computeHmac(secretKey, sigInput);
byte[] actualSig   = Base64.getUrlDecoder().decode(parts[2]);
if (!MessageDigest.isEqual(expectedSig, actualSig)) throw new SecurityException("Invalid signature");
// Decode payload and check exp:
String payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]));
// parse JSON and check exp > now

Using java-jwt Library (Auth0)

The com.auth0:java-jwt library simplifies JWT creation and verification with a fluent API.

// Create:
Algorithm alg = Algorithm.HMAC256(secretKey);
String token = JWT.create()
    .withSubject("user-42")
    .withClaim("role", "ADMIN")
    .withExpiresAt(Instant.now().plusSeconds(3600))
    .sign(alg);
// Verify:
JWTVerifier verifier = JWT.require(alg).withIssuer("my-service").build();
DecodedJWT decoded = verifier.verify(token);
System.out.println(decoded.getSubject());

HS256 vs RS256

HS256 uses a shared symmetric key — simple but both issuer and verifier must trust each other with the key. RS256 uses RSA: sign with private key, verify with public key — suitable for multi-service architectures where any service verifies without knowing the signing key.

Storing JWTs: HttpOnly Cookies vs localStorage

Store JWTs in HttpOnly cookies (not accessible from JS — prevents XSS theft) with Secure and SameSite=Strict flags. Avoid localStorage — XSS attacks can read it.

// Set JWT as HttpOnly cookie in Spring:
ResponseCookie cookie = ResponseCookie.from("jwt", token)
    .httpOnly(true).secure(true).sameSite("Strict")
    .path("/").maxAge(3600).build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());

Refresh Tokens

JWTs have short expiry (15 min). Refresh tokens (opaque, stored server-side) have longer expiry. The client exchanges a refresh token for a new JWT without re-authenticating.

JWT Revocation Challenge

JWTs are stateless — there is no built-in revocation. Use a short expiry + a blocklist of revoked JWT IDs (jti claim) in Redis to support logout before expiry.

// On logout, add the jti to a Redis blocklist with TTL = token expiry:
redis.set("revoked:" + jti, "1", ex, 3600);
// On verify, check blocklist:
if (redis.exists("revoked:" + decoded.getId())) throw new SecurityException("Token revoked");

Spring Security JWT Integration

In Spring Security, implement JwtAuthenticationFilter extends OncePerRequestFilter to extract, verify, and set the SecurityContext from the JWT on each request.

String token = request.getHeader("Authorization").replace("Bearer ","");
DecodedJWT decoded = verifier.verify(token);
String userId = decoded.getSubject();
UsernamePasswordAuthenticationToken auth =
    new UsernamePasswordAuthenticationToken(userId, null, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);

Quick Check

What is the key structural difference between HS256 and RS256 JWT signing?

Recap

JWT = header.payload.signature (Base64URL). Sign with HMAC (HS256) or RSA (RS256). Verify signature and exp claim. Store in HttpOnly cookies. Use short expiry + refresh tokens. Revoke via jti blocklist in Redis.

Frequently asked questions

Is the “JWT: Structure, Creation, and Verification” lesson free?

Yes — the full text of “JWT: Structure, Creation, and Verification” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.

What will I learn in “JWT: Structure, Creation, and Verification”?

Manually decode JWT structure, create signed tokens with a secret, and verify claims without frameworks. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Java Academy?

No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “JWT: Structure, Creation, and Verification” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Java Academy lesson?

Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Cryptographic Hashing with MessageDigest
  2. AES Symmetric Encryption
  3. HMAC-SHA256 for Message Integrity
  4. JWT: Structure, Creation, and Verification
← Back to Java Academy