Configure CORS for specific URLs in Confluence 7.15+
Summary
Previously, CORS (cross-origin resource sharing) can be configured for specific URLs using filters in the web.xml. Following the web.xml cleanup performed as part of CONFSRVDEV-21301, this is no longer possible.
Environment
Confluence versions above 7.15
Diagnosis
To confirm whether the Confluence instance supports CORS, look for the Access-Control-Allow-Origin header in the response by running the following CURL command against your Confluence instance. For example, if the origin URL and Confluence are on different addresses:
curl -L -k -H "Origin: https://www.my-origin-url.com" -u admin:admin-pword -v https://<confluence-base-url>/rest/api/user\?username\=admin -D ~/Downloads/headers.txt
Solution
Starting from Confluence 7.15+, the web.xml config file was cleaned up and made programmatic. As a result, the previous CORS configuration will no longer work. Given that this is no longer possible within Confluence itself, use the alternative configuration described below to replace the previous CORS configuration.
Confluence hosted behind a reverse proxy or the load balancer
To enable Access-Control-Allow-Origin headers, configure a reverse proxy (or load balancer) to send the CORS response headers. Here are a few examples of CORS configurations.
For Apache
To add the CORS authorization to the header using Apache, simply add the following lines inside either the <Directory>
, <Location>
, <Files>
or <VirtualHost>
sections of your server config (usually located in a *.conf
file, such as httpd.conf
or apache.conf
) or within a .htaccess
file:
For example
<VirtualHost *:443>
ServerName service.com
# Set CORS headers to allow XHR
# Determine if Origin matches the regex
SetEnvIf Origin "http(s)?://(www.api-client.com|beta.api-client.com:8000)$" AccessControlAllowOrigin=$0
# Set Access-Control-Allow-Origin if the Origin is allowd
Header always set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header always set Access-Control-Allow-Credentials true
Header always set Access-Control-Allow-Headers "Origin, Authorization, Accept"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "600"
Header always set Access-Control-Expose-Headers "Access-Control-Allow-Origin, Access-Control-Allow-Credentials"
Header merge Vary Origin
# Answer pre-flight requests with a 204 No Content
# https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=204,L]
# Include an appropriate proxy configuration here
# Example proxy configuration for an internal service at port 8080
ProxyPreserveHost On
ProxyPass /confluence http://localhost:8090/confluence nocanon
ProxyPassReverse /confluence http://localhost:8090/confluence
ProxyRequests Off
<Location /confluence>
Require all granted
</Location>
# Include an appropriate SSL configuration here
</VirtualHost>
Here, we used the
SetEnvIf
directive to set the environment variable AccessControlAllowOrigin
conditionally based on whether the Origin
parameter matches a PCRE regex. In this example, try to match both http
and https
of both www.api-client.com
and beta.api-client.com:8000
.
For NGINX
CORS can be enabled using the Headers core module which is compiled into nginx by default. Add the following lines inside the location
section of your server config (usually located in a *.conf
file, such as nginx.conf
).
For example:
location /confluence {
#
# Answer pre-flight requests with a 204 No Content
#
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://www.api-client.com,https://beta.api-client.com:8000';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 600;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' 'https://www.api-client.com,https://beta.api-client.com:8000' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Expose-Headers' 'Access-Control-Allow-Origin, Access-Control-Allow-Credentials' always;
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' 'https://www.api-client.com,https://beta.api-client.com:8000' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Expose-Headers' 'Access-Control-Allow-Origin, Access-Control-Allow-Credentials' always;
}
proxy_pass http://localhost:8090/confluence;
}
Here we set the header
Access-Control-Allow-Origin
to a comma-separated list of URLs that need access to Confluence.