Why Token Pass‑Through Fails and How to Build Secure Unified Auth in Microservices
This article examines the pitfalls of token pass‑through authentication in microservices, proposes explicit userId parameter passing, compares unified auth approaches using Spring Cloud Gateway with Feign or Dubbo, and explores non‑unified alternatives, including K8s Ingress integration and practical code examples.
1. Token
1.1 Token Pass‑Through (Not Recommended)
When first learning microservices, many online solutions suggest passing the Token for authentication. This approach lets each microservice obtain the current user information, which may be convenient but is a poor design.
Reason 1: Internal and external APIs become mixed and hard to distinguish.
Reason 2: Internal microservice APIs should be stateless to ensure atomicity and improve code reuse.
In other words, Service B should not need to know whether the request is authenticated; the first service in the routing layer should validate the token and pass necessary parameters downstream. Consider these scenarios:
User signs in and gains points.
Admin manually adds points to a user.
Distributed scheduler batch adds points.
If the points service only provides an API that adds points based on the current logged‑in user ID, scenario 2 would require a separate API because the logged‑in entity is an admin, not the target user, reducing code reuse.
1.2 Explicit Parameter Passing (Recommended)
The first service in the route parses the Token, extracts the userId, and passes it explicitly to downstream services, which no longer need to parse the Token. A single API that accepts userId satisfies all three scenarios, preserving atomicity and improving reuse.
Note: The provided API should not be exposed to the external network; internal APIs must be distinguished, e.g., using a path pattern like /api/inside/** , and the gateway should reject external requests to these endpoints.
2. Unified Authorization
2.1 Feign Internal Call
Spring Cloud Gateway + Feign internal calls centralize authentication at the gateway. After verification, the gateway adds user information (e.g., userId) to request headers for downstream services.
Drawback: Service A must define an internal Controller in Service B for Feign to call, increasing code volume.
2.2 Dubbo Internal Call
Spring Cloud Gateway + Dubbo internal calls also centralize authentication at the gateway and forward user information via headers.
Advantages: No extra Controller is needed; only local service and remote DubboService differ, making the code cleaner.
Disadvantages: Slightly increases the technology stack complexity.
2.3 Spring Boot Web + Dubbo (No Gateway)
This design removes the gateway and uses a Spring Boot Web project to perform unified authentication and authorization. The web container should be Undertow (non‑blocking) rather than Tomcat for better throughput.
All service Controllers are integrated into the web application; each service can provide its own Controller module, while the web gateway only contains a startup class that depends on these modules.
Advantages: Simplifies project structure; only service code remains, and performance testing does not need to consider the gateway thread pool.
Disadvantages: Dynamic route configuration via a configuration center is not possible; adding a new service requires redeployment.
3. Non‑Unified Authorization
In this approach, the gateway performs only routing, while each service implements its own authentication, possibly sharing a common auth library.
3.1 Conventional Mode
A generic authentication module is packaged as a jar and integrated into each service. The module provides:
JWT token parsing
Permission interception
Caching (local or Redis)
This mode suits large teams where each microservice is owned by a different group, allowing each service to maintain its own permission rules while sharing the same rule definitions.
3.2 Integration with K8s
When the application gateway is replaced by a K8s Ingress gateway, the Ingress forwards traffic to services via K8s Service load balancing, eliminating the need for a separate service registry.
Example service address: http://goods-svc:8080/api/goods/info/10001 or dubbo://goods-svc:20880.
Feign Example
@FeignClient(name = "user-service", url = "http://goods-svc:8080")
public interface UserServiceClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
}Dubbo Example
@Reference(url = "dubbo://goods-svc:20880")
private DemoService demoService;The choice between unified and non‑unified authorization depends on project requirements; both approaches are viable.
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.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
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.
