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>

(info)  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;
}

(info) Here we set the header Access-Control-Allow-Origin to a comma-separated list of URLs that need access to Confluence.


Last modified on Jan 7, 2025

Was this helpful?

Yes
No
Provide feedback about this article
Powered by Confluence and Scroll Viewport.