Web

Fix 403 Forbidden for Swagger UI in Spring Boot Security

Fix 403 Forbidden for Swagger UI in Spring Boot by permitting /v3/api-docs/**, /swagger-ui/** and /webjars/** in Spring Security and handling CSRF for docs.

1 answer 1 view

Why does Spring Boot return 403 Forbidden when accessing Swagger UI (http://localhost:9002/swagger-ui/index.html) despite permitting /swagger-ui/** and /v3/api-docs/** in Spring SecurityConfig?

Setup Details

  • Spring Boot version: 3.4.2 (parent)
  • Dependency: org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0

application.properties

properties
springdoc.api-docs.enabled=true
springdoc.swagger-ui.enabled=true

Relevant SecurityConfig.java

java
http.authorizeHttpRequests(auth -> auth
 .requestMatchers(
 "/nonLoggedUsers/**","/pokemonData/**","/natureData/**",
 "/itemData/allItems","/something_something/**",
 "/v3/api-docs/**","/swagger-ui/**"
 ).permitAll()
 .anyRequest().authenticated()
);

Other endpoints work correctly, but OpenAPI/Swagger paths are blocked with 403. How to fix this?

Spring Boot returns 403 Forbidden for Swagger UI most commonly because Spring Security is blocking the Swagger static assets or the OpenAPI endpoint (often the /webjars/** assets or index path) even when you permitted /swagger-ui/** and /v3/api-docs/**. Fix it by explicitly permitting the webjars path and exact index paths (e.g., /swagger-ui/index.html, /swagger-ui.html), and by handling CSRF for the docs endpoints (ignore CSRF for those paths or disable it in dev); matcher order matters. Apply the change in your SecurityFilterChain so the permitAll rules run before .anyRequest().authenticated().


Contents


Why Spring Boot returns 403 Forbidden for Swagger UI

Short answer: the browser requests that render the UI are being blocked by Spring Security — usually static JS/CSS served from webjars or the API JSON at /v3/api-docs — so the UI can’t load and you see 403.

What actually happens (common causes)

  • Missing /webjars/** permit: springdoc (and older Swagger setups) serves UI assets from webjars. If you only permit /swagger-ui/** but not /webjars/, the browser’s requests for swagger-ui JavaScript/CSS get 403 and the UI appears broken or forbidden. See the springdoc guidance and community reports describing exactly this symptom: missing /webjars/ produces 403 on static assets (springdoc GitHub, Stack Overflow example).
  • Exact index path not matched: the UI page can be requested as /swagger-ui/index.html or legacy /swagger-ui.html; if your matcher set doesn’t include the exact path the initial page may be blocked.
  • CSRF protection blocking API fetches: Swagger UI makes XHR/fetch requests to /v3/api-docs and to endpoints used by Try-it-out; if CSRF protection rejects those requests you’ll see 403 responses for POSTs or even GETs in some configurations (Stack Overflow example on CSRF causing 403).
  • Matcher DSL / ordering issues: Spring Security evaluates matchers in order. The permitAll for Swagger must be present before a catch-all that requires authentication. Also make sure you’re using the right matcher DSL for your stack (servlet vs reactive).

Why this matters with your setup

  • You’re on Spring Boot 3.4.2 with springdoc-openapi-starter-webmvc-ui 2.6.0 — springdoc expects the docs paths and static resources to be available, and the project docs explicitly call out permitting /v3/api-docs/** and /webjars/** when Spring Security is enabled (springdoc FAQ).

Fix: update Spring SecurityConfig (code examples)

Minimal and immediate change

  • Add the webjars pattern and the index paths to your permit list. Example quick change that often resolves the 403:
java
http.authorizeHttpRequests(auth -> auth
 .requestMatchers(
 "/nonLoggedUsers/**","/pokemonData/**","/natureData/**",
 "/itemData/allItems","/something_something/**",
 "/v3/api-docs/**",
 "/swagger-ui/**",
 "/swagger-ui/index.html",
 "/swagger-ui.html",
 "/webjars/**"
 ).permitAll()
 .anyRequest().authenticated()
);

Robust SecurityFilterChain example (servlet stack)

  • This example adds explicit CSRF ignoring for doc endpoints (safer than disabling CSRF globally) and keeps your permit rules first:
java
import org.springframework.context.annotation.Bean;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 // Ignore CSRF for OpenAPI + Swagger static resources
 http.csrf(csrf -> csrf.ignoringRequestMatchers(
 new AntPathRequestMatcher("/v3/api-docs/**"),
 new AntPathRequestMatcher("/swagger-ui/**"),
 new AntPathRequestMatcher("/webjars/**")
 ));

 http.authorizeHttpRequests(auth -> auth
 .requestMatchers(
 "/nonLoggedUsers/**","/pokemonData/**","/natureData/**",
 "/itemData/allItems","/something_something/**",
 "/v3/api-docs/**","/swagger-ui/**","/swagger-ui/index.html",
 "/swagger-ui.html","/webjars/**"
 ).permitAll()
 .anyRequest().authenticated()
 );

 // configure login/oauth as you need
 return http.build();
}

Quick dev-only shortcut

  • For local development you can temporarily disable CSRF entirely (not recommended for production):
java
http.csrf().disable();

Reactive apps

  • If you’re on WebFlux, the equivalent is authorizeExchange().pathMatchers(…).permitAll() and you may need to tweak the CSRF handling accordingly.

Also include both /swagger-ui/** and /webjars/** — community reports and the springdoc repo call this out as the reason a UI returns 403 even when /swagger-ui/** looks permitted (Stack Overflow example, springdoc repo).


CSRF and production-safe options

You want the docs usable but not insecure. Options:

  • Ignore CSRF only for the docs endpoints (shown above with AntPathRequestMatcher). That keeps CSRF for your app but lets Swagger UI fetch the OpenAPI JSON and perform try-it-out requests.
  • Expose Swagger UI only for certain profiles (dev/staging). Put the swagger UI and springdoc.properties behind a profile: set springdoc.swagger-ui.enabled=true only for the dev profile and keep it off in production.
  • Put the docs behind an authenticated admin page or network boundary (VPN/internal-only). Sometimes the simplest pattern is to keep swagger UI available only on non-prod ports or behind firewall rules.

Tip: the springdoc FAQ and repo discuss CSRF and recommend permitting the docs paths when security is present — check their guidance for the version you use (springdoc FAQ, springdoc repo).


Troubleshooting checklist & browser diagnostics

Before and after changes, do these checks:

  1. Browser devtools → Network tab
  1. Direct curl tests
  1. Enable Spring Security debug logging temporarily
  • application.properties: logging.level.org.springframework.security=DEBUG
  • Look for how matchers are evaluated and which rule returns 403.
  1. Verify matcher DSL and ordering
  • Ensure your permitAll requestMatchers are registered before anyRequest().authenticated().
  • If you have multiple SecurityFilterChain beans, confirm the chain that handles swagger paths is active and ordered correctly.
  1. Check for other filters (CORS, custom filters) that might return 403 for preflight or XHR.
  2. Verify springdoc version behavior
  • Some springdoc releases moved assets; check the repo or changelog for your 2.6.0 version if behavior differs (springdoc issues).

If you still see 403 after permitting /webjars/, /swagger-ui/ and handling CSRF, capture the exact failing request URL and paste it into a browser or curl — that usually points straight to the missing permit rule.


Sources


Conclusion

The 403 Forbidden for Swagger UI in Spring Boot is almost always caused by Spring Security blocking static assets or the OpenAPI endpoint — add explicit permits for /webjars/** and the exact index paths, and handle CSRF for the docs endpoints (ignore CSRF for /v3/api-docs/** and related paths or disable it only in dev). With those changes to your Spring SecurityConfig the springdoc OpenAPI Swagger UI should load normally.

Authors
Verified by moderation
Moderation
Fix 403 Forbidden for Swagger UI in Spring Boot Security