Skip to content

Fix CORS for *authenticated* cross-origin requests#299

Open
petersmythe wants to merge 1 commit into
geoserver:masterfrom
petersmythe:fix/cors-authorization-header
Open

Fix CORS for *authenticated* cross-origin requests#299
petersmythe wants to merge 1 commit into
geoserver:masterfrom
petersmythe:fix/cors-authorization-header

Conversation

@petersmythe
Copy link
Copy Markdown
Contributor

Summary

When CORS_ENABLED=true is set without additional configuration, authenticated cross-origin requests (e.g. from Swagger UI or JavaScript clients sending Authorization headers) fail. This PR fixes two issues that combine to break CORS for any endpoint protected by Spring Security.

Problems

  1. Missing Authorization in default CORS_ALLOWED_HEADERS — The default does not include Authorization, so Tomcat's CorsFilter rejects preflight requests that declare Access-Control-Request-Headers: authorization with a 403 Forbidden.

  2. CORS filter-mapping placed after Spring Security — The CORS <filter-mapping> is appended just before </web-app>, placing it AFTER filterChainProxy in the servlet filter chain. Spring Security intercepts the unauthenticated OPTIONS preflight request first and returns 401 before the CORS filter ever runs.

Fix

  • Add Authorization to the default CORS_ALLOWED_HEADERS environment variable in the Dockerfile.
  • Split the CORS web.xml injection into two steps: the <filter> definition is still appended before </web-app>, but the <filter-mapping> is now inserted BEFORE the filterChainProxy filter-mapping so that preflight requests are handled before authentication is enforced.
  • Update README.md to reflect the new default.

Testing

Verified with docker.osgeo.org/geoserver:3.0.x:

  • Before: OPTIONS /geoserver/rest/about/manifest with Origin and Access-Control-Request-Headers: Authorization → 401
  • After: same request → 200 with correct CORS headers

No changes to existing behaviour for non-credentialed requests or when CORS_ENABLED=false.

Two issues prevented CORS from working with authenticated requests
(e.g. Swagger UI 'Try it out', JavaScript clients with Basic Auth):

1. Missing Authorization header in CORS_ALLOWED_HEADERS default:
   The default did not include 'Authorization', causing Tomcat's
   CorsFilter to reject preflight requests that declare
   Access-Control-Request-Headers: authorization.

2. CORS filter-mapping placed after Spring Security:
   The filter-mapping was appended at the end of web.xml (before
   </web-app>), which placed it AFTER the filterChainProxy
   filter-mapping. This meant Spring Security intercepted OPTIONS
   preflight requests first and returned 401 Unauthorized before
   the CORS filter could respond with the required headers.

Fix:
- Add 'Authorization' to the default CORS_ALLOWED_HEADERS env var
- Insert the CORS filter-mapping BEFORE filterChainProxy in web.xml
  so preflight requests are handled before authentication is enforced
- Update README.md to reflect the new default
@petersmythe petersmythe requested a review from buehner May 22, 2026 10:09
@petersmythe petersmythe changed the title Fix CORS for authenticated cross-origin requests Fix CORS for *authenticated* cross-origin requests May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants