Designing User Authentication in Microservice Architecture with JWT and Gateway

This article explains traditional session‑based authentication, introduces JWT and JJWT, and presents two microservice authentication patterns—service‑side verification and gateway‑side verification—detailing their workflows, code examples, advantages, drawbacks, and practical challenges.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Designing User Authentication in Microservice Architecture with JWT and Gateway

In a monolithic single‑point application, user authentication is performed by validating username and password and storing the user object in the Tomcat session, which works fine until the system is scaled horizontally with Nginx load balancing.

When requests are routed to different nodes, the session data stored locally on one Tomcat instance is not available on others, causing users to be forced to log in again after a page refresh. The root cause is the stateful session storage, which requires session replication or a shared store.

To solve this, a distributed session solution based on Redis is introduced, where all user sessions are stored centrally in Redis, eliminating consistency problems but creating a new bottleneck because Redis must handle all authentication traffic.

A more scalable design moves the user data to the client side: after successful login, user information is stored in cookies or LocalStorage, and each request carries this data to the backend. Because the data is stored on the client, the backend is not burdened, but the data must be encrypted.

JSON Web Token (JWT) is the standard solution for client‑side encrypted data. A JWT consists of three Base64‑encoded parts separated by dots: Header, Payload, and Signature. The header specifies the token type and signing algorithm (e.g., HS256). The payload contains user claims such as "sub", "name", and custom fields. The signature is generated by applying the chosen algorithm to the header and payload using a secret key.

Example JWT string:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJ1c2VySWRcIjoyLFwidXNlcm5hbWVcIjpcImxpc2lcIixcIm5hbWVcIjpcIuadjuWbm1wiLFwiZ3JhZGVcIjpcInZpcFwifSJ9.NT8QBdoK4S-PbnhS0msJAqL0FG2aruvlsBSyG226HiU

The header JSON: {"alg":"HS256","typ":"JWT"} The payload JSON: {"sub":"1234567890","name":"John Doe","admin":true} JJWT is a popular Java library for creating and verifying JWTs. 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 in a test case:

@SpringBootTest
public class JwtTestor {
    /** Create Token */
    @Test
    public void createJwt() {
        // private key
        String key = "1234567890_1234567890_1234567890";
        // 1. Base64 encode the key
        String base64 = new BASE64Encoder().encode(key.getBytes());
        // 2. Generate SecretKey (algorithm chosen automatically)
        SecretKey secretKey = Keys.hmacShaKeyFor(base64.getBytes());
        // 3. Build JWT with payload
        String data = "{\"userId\":123}"; // payload data
        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<Claims> 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 authentication schemes for microservices are described:

Service‑side verification: The authentication center issues JWTs; each microservice, upon receiving a request with a JWT, forwards the token to the authentication service for verification and then obtains user and permission data before executing business logic.

Gateway‑side verification: The API gateway validates the JWT against the authentication center before routing, attaching the user and permission information to the downstream request, thus offloading verification from individual services.

Service‑side verification offers fine‑grained control (e.g., only protect specific methods) but requires developers to annotate or configure verification points. Gateway verification simplifies development and reduces coupling but may introduce extra network latency because every request with a JWT triggers a remote verification.

Choosing between them depends on scenario: low‑latency, high‑concurrency systems (e.g., real‑time trading) benefit from service‑side verification, while traditional enterprise applications may prefer gateway verification for easier maintenance.

Practical challenges include JWT expiration handling—since JWTs have fixed lifetimes, projects often set them to “permanent” and control validity via Redis expiration, effectively making JWTs stateful. Caching user/permission data after the first verification can improve performance but adds consistency concerns.

In summary, the article reviews session‑based authentication, introduces JWT and JJWT usage, and compares two microservice authentication architectures, highlighting trade‑offs and real‑world considerations.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MicroservicesSecurityAuthenticationSpring CloudJWT
Code Ape Tech Column
Written by

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

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.