How to configure CORS on WildFly

This articles discusses about Cross-origin HTTP requests (CORS) and how they can be enabled on WildFly.

Let0s start with some definitions: a cross-origin HTTP request is one that is made to:

  • A different domain (for example, from acme.com to amazon.com).
  • A different subdomain (for example, from acme.com to home.acme.com).
  • A different port (for example, from acme.com:8080 to acme.com:8180).
  • A different protocol (for example, from https://acme.com to http://acme.com)

There are two types of CORS: simple requests and non-simple requests.

A CORS request is simple if the following conditions are met:

  • It is issued against an API resource that allows only GET, HEAD, and POST requests.
  • If it is a POST method request, it must include an Origin header.
  • The request payload content type is text/plain, multipart/form-data, or application/x-www-form-urlencoded.
  • The request does not contain custom headers.

For simple CORS POST method requests, the response from your resource needs to include the following Header:

Access-Control-Allow-Origin: *

Or the Header is set to the origins allowed to access that resource.

All other CORS requests are non-simple requests and therefore you need to enable CORS support.

How to enable CORS in WildFly

When a browser receives a non-simple HTTP request, the CORS protocol requires the browser to send a preflight request to the server and wait for approval (or a request for credentials) from the server before sending the actual request. The preflight request appears to your API as an HTTP request that:

  • Includes an Origin header.
  • Uses the OPTIONS method.
  • Includes at least the following headers: Access-Control-Request-Method Access-Control-Request-Headers

Let’s see how to configure it in practice on WildFly application server. Start the CLI from the bin folder of the application server.

$ ./jboss-cli.sh -c

We will update Undertow’s configuration. At first, we will at first add a filter on the default server to add Access-Control-Allow Header settings:

/subsystem=undertow/server=default-server/host=default-host/filter-ref="Access-Control-Allow-Origin":add()
/subsystem=undertow/server=default-server/host=default-host/filter-ref="Access-Control-Allow-Methods":add()
/subsystem=undertow/server=default-server/host=default-host/filter-ref="Access-Control-Allow-Headers":add()
/subsystem=undertow/server=default-server/host=default-host/filter-ref="Access-Control-Allow-Credentials":add()
/subsystem=undertow/server=default-server/host=default-host/filter-ref="Access-Control-Max-Age":add()

Then, we will include in the Response the Access-Control-Allow Headers for all HTTP Methods:

/subsystem=undertow/configuration=filter/response-header="Access-Control-Allow-Origin":add(header-name="Access-Control-Allow-Origin",header-value="*")
/subsystem=undertow/configuration=filter/response-header="Access-Control-Allow-Methods":add(header-name="Access-Control-Allow-Methods",header-value="GET, POST, OPTIONS, PUT")
/subsystem=undertow/configuration=filter/response-header="Access-Control-Allow-Headers":add(header-name="Access-Control-Allow-Headers",header-value="accept, authorization, content-type, x-requested-with")
/subsystem=undertow/configuration=filter/response-header="Access-Control-Allow-Credentials":add(header-name="Access-Control-Allow-Credentials",header-value="true")
/subsystem=undertow/configuration=filter/response-header="Access-Control-Max-Age":add(header-name="Access-Control-Max-Age",header-value="1")

The expected XML configuration follows here:

 <subsystem xmlns="urn:jboss:domain:undertow:11.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
    <buffer-cache name="default"/>
    <server name="default-server">
        <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
        <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
        <host name="default-host" alias="localhost">
            <location name="/" handler="welcome-content"/>
            <http-invoker security-realm="ApplicationRealm"/>
                <filter-ref name="server-header"/>
                <filter-ref name="x-powered-by-header"/>
                <filter-ref name="Access-Control-Allow-Origin"/>
                <filter-ref name="Access-Control-Allow-Methods"/>
                <filter-ref name="Access-Control-Allow-Headers"/>
                <filter-ref name="Access-Control-Allow-Credentials"/>
                <filter-ref name="Access-Control-Max-Age"/>
        </host>
    </server>
    <servlet-container name="default">
        <jsp-config/>
        <websockets/>
    </servlet-container>
    <handlers>
        <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
    </handlers>
    <filters>
        <response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
        <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
        <response-header name="Access-Control-Allow-Origin" header-name="Access-Control-Allow-Origin" header-value="*"/>
        <response-header name="Access-Control-Allow-Methods" header-name="Access-Control-Allow-Methods" header-value="GET, POST, OPTIONS, PUT"/>
        <response-header name="Access-Control-Allow-Headers" header-name="Access-Control-Allow-Headers" header-value="accept, authorization, content-type, x-requested-with"/>
        <response-header name="Access-Control-Allow-Credentials" header-name="Access-Control-Allow-Credentials" header-value="true"/>
        <response-header name="Access-Control-Max-Age" header-name="Access-Control-Max-Age" header-value="1"/>
    </filters>
</subsystem>

With this configuration in place, you have enabled CORS in WildFly application server.