🧭 Overview
This document explains how Swagger UI is aggregated across multiple microservices behind a Spring Cloud Gateway, detailing the request flow and how security is managed.
In my adventuretube microserice. It does require two separate two-phase of integration
🛠️ Two-Phase Integration Overview
🔹 Step 1: Swagger Configuration for Each Service
Each microservice is configured with Springdoc OpenAPI to generate Swagger documentation. These are then aggregated through the Gateway using predefined routes and exposed under a unified Swagger UI.
🔹 Step 2: Security Configuration for Microservices
After setting up the gateway forwarding, security configurations within each microservice must be adjusted to permit access to documentation endpoints (/v3/api-docs
, /swagger-ui/**
) while still protecting business logic routes with JWT-based filters.
✅ Request Flow Summary
1. Initial Swagger UI Request
A user accesses the Swagger UI at:
https://api.adventuretube.net/swagger-ui/index.html
This triggers Springdoc in the gateway-service, using the following config:
springdoc:
swagger-ui:
enabled: true
path: /swagger-ui.html
urls:
- name: Auth Service
url: /auth-service/v3/api-docs
- name: Member Service
url: /member-service/v3/api-docs
- name: Web Service
url: /web-service/v3/api-docs
- name: Geospatial Service
url: /geo-service/v3/api-docs
api-docs:
enabled: true
These
urls
define the destinations Swagger UI will call through the gateway.
2. Gateway Routing and Security
In
GatewayConfig.java
, all primary API routes (e.g.,/auth/**
,/member/**
, etc.) are configured with.filters(f -> f.filter(filter))
. This means every incoming request is:Intercepted by the global custom
AuthenticationFilter
, andForwarded to the appropriate microservice with the
/XXX-service
prefix stripped. For example,/auth-service/xyz
is forwarded as/xyz
toauth-service
.
The
AuthenticationFilter
checks whether a request requires JWT authentication.The decision is delegated to
RouterValidator
, which evaluates whether the request matches any open endpoints that should bypass authentication.
🔐 RouterValidator
includes:
List.of(
"^/auth-service/v3/api-docs.*",
"^/member-service/v3/api-docs.*",
"^/web-service/v3/api-docs.*",
"^/geo-service/v3/api-docs.*",
"^/swagger-ui.*"
)
These paths are considered open endpoints, so while the filter still runs, it allows these requests through without token validation.
3. Route Forwarding
Each Swagger doc route uses
.stripPrefix(1)
to clean up the path:
.route("auth-docs", r -> r.path("/auth-service/v3/api-docs")
.filters(f -> f.stripPrefix(1))
.uri("lb://auth-service"))
This forwards:
From:
/auth-service/v3/api-docs
To:
/v3/api-docs
inside the target microservice
🧩 Microservice Swagger Handling
🔐 Auth Service
When the gateway forwards a request to /auth-service/v3/api-docs
, the route is stripped to /v3/api-docs
and passed to auth-service
.
Spring Security Filter Chain Engaged: The request hits
auth-service
‘s Spring Security configuration:
@Bean
@Order(1)
public SecurityFilterChain apiFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf(AbstractHttpConfigurer::disable)
.securityMatcher("/auth/**")
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(
"/auth/register",
"/auth/login",
"/auth/refreshToken",
"/auth/logout",
"/swagger-ui.html",
"/swagger-ui/**",
"/v3/api-docs",
"/v3/api-docs/**"
).permitAll()
.anyRequest().hasRole("ADMIN")
);
return httpSecurity.build();
}
Explanation:
The
securityMatcher("/auth/**")
targets only routes under/auth/
.The
/v3/api-docs
and related Swagger UI routes are listed as public using.permitAll()
.Other paths require the
ADMIN
role and a valid JWT token.No
httpBasic()
is configured since downstream services are authenticated using JWT, not username/password.