Designing User Authentication in Microservice Architecture with JWT and Spring Cloud Gateway
This article explains traditional session‑based authentication, introduces JWT and JJWT usage with Java code examples, and compares two microservice authentication designs—service‑side verification and API‑gateway unified verification—while discussing their trade‑offs, challenges, and practical implementation tips.
In microservice environments, user authentication must confirm a user's identity before providing services. Traditional monolithic authentication stores session data in Tomcat's memory, which fails under load‑balanced clusters, leading to the adoption of Redis for distributed session storage. However, Redis can become a bottleneck at massive scale.
To avoid server‑side state, client‑side storage using JWT (JSON Web Token) is introduced. JWT is an encrypted, time‑limited token containing user information, typically consisting of a Header, Payload, and Signature.
Example JWT string:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJ1c2VySWRcIjoyLFwidXNlcm5hbWVcIjpcImxpc2lcIixcIm5hbWVcIjpcIuadjuWbm1wiLFwiZ3JhZGVcIjpcInZpcFwifSJ9.NT8QBdoK4S-PbnhS0msJAqL0FG2aruvlsBSyG226HiUThe Header specifies the token type and signing algorithm (e.g., HS256). The Payload carries user data such as "sub", "name", and custom claims. The Signature is generated by applying the chosen algorithm to the Base64Url‑encoded Header and Payload together with a secret key.
JJWT, a popular Java library, simplifies JWT creation and verification. Adding the Maven dependencies:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>Creating a JWT:
@SpringBootTest
public class JwtTestor {
/** Create Token */
@Test
public void createJwt() {
// private key
String key = "1234567890_1234567890_1234567890";
// Base64 encode the key
String base64 = new BASE64Encoder().encode(key.getBytes());
// Generate SecretKey object
SecretKey secretKey = Keys.hmacShaKeyFor(base64.getBytes());
// payload data
String data = "{\"userId\":123}";
String jwt = Jwts.builder().setSubject(data).signWith(secretKey).compact();
System.out.println(jwt);
}
}Verifying a JWT:
/** Verify and extract JWT data */
@Test
public void checkJwt() {
String jwt = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJ1c2VySWRcIjoxMjN9In0.1p_VTN46sukRJTYFxUg93CmfR3nJZRBm99ZK0e3d9Hw";
String key = "1234567890_1234567890_1234567890";
String base64 = new BASE64Encoder().encode(key.getBytes());
SecretKey secretKey = Keys.hmacShaKeyFor(base64.getBytes());
try {
JwtParser parser = Jwts.parserBuilder().setSigningKey(secretKey).build();
Jws
claimsJws = parser.parseClaimsJws(jwt);
String subject = claimsJws.getBody().getSubject();
System.out.println(subject);
} catch (JwtException e) {
System.out.println("Jwt verification failed");
e.printStackTrace();
}
}Two microservice authentication schemes are presented:
Service‑side verification: The authentication service issues JWTs; downstream services forward the token back to the auth service for verification and retrieve user/permission data.
API‑gateway unified verification: The gateway validates JWTs with the auth service before routing, attaching user information to the request.
Service‑side verification offers fine‑grained control suitable for low‑latency, high‑concurrency scenarios, while gateway verification simplifies development at the cost of additional remote calls.
Challenges include fixed JWT expiration, the need for token renewal, and the trade‑off between statelessness and using Redis to manage token revocation or dynamic expiration. Caching user data after the first verification can improve performance but introduces consistency concerns.
In summary, the article reviews session‑based authentication, demonstrates JWT creation and verification with JJWT, compares two microservice authentication architectures, and discusses practical considerations such as token lifecycle, caching, and scenario‑based design choices.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.