How to resolve CORS issues with Keycloak and Apache

Dealing with Cross-Origin Resource Sharing (CORS) issues is a common challenge when integrating Keycloak with diverse client applications hosted on different domains. This article addresses CORS-related hurdles encountered during the integration process and provides a comprehensive guide to resolving them. Starting with the manifestation of CORS issues and progressing through Keycloak configuration and Apache reverse proxy settings, this article aims to equip developers with practical solutions for enabling seamless communication between Keycloak and multiple client applications across varied domains.

Some of the common errors we encountered during the tuning process:

Access to XMLHttpRequest at 'https://id.qa2.smartwcm.swcm.link/realms/smark/protocol/openid-connect/token' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Access to XMLHttpRequest at 'https://id.qa2.smartwcm.swcm.link/realms/smark/protocol/openid-connect/token' from origin 'http://localhost:3000' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'https://smark-web.qa2.smark.swcm.link,http://localhost:3000', but only one is allowed.

Configuration on the Keycloak application

When a client application (such as a ReactJS app) attempts to make a cross-origin request to the Keycloak server, the server checks the "Web Origins" configuration to determine whether the request is allowed. If the origin of the request matches one of the specified web origins, the request is allowed; otherwise, it may be blocked due to CORS restrictions.

Here's how you can set the "Web Origins" in Keycloak:

  • Log in to the Keycloak Admin Console:
    • Open your browser and navigate to the Keycloak Admin Console URL.
    • Log in with your administrative credentials.
  • Select Your Realm:
    • In the Keycloak Admin Console, select the realm for which you want to configure web origins.
  • Navigate to Realm Settings:
    • Click on "Realm Settings" in the left sidebar.
  • Configure Web Origins:
    • Find the "Web Origins" field.
    • Add the origins that correspond to the URLs of your client applications.

  • I have the following as the values of Web Origins. The URL http://localhost:3000/* is added for the local development and is not added in the Apache.

    https://smark-web.qa1.smark.swcm.link/*
    https://smark-web.qa2.smark.swcm.link/*
    http://localhost:3000/*

  • Save the Configuration:
    • After adding the necessary web origins, save the configuration.

Apache Reverse Proxy Configuration


ServerName id.qa1.smartwcm.swcm.link
ServerAlias id.qa2.smartwcm.swcm.link
ErrorLog /var/log/apache2/id.qa.smartwcm.swcm.link-error.log
CustomLog /var/log/apache2/id.qa.smartwcm.swcm.link-access.log combined

SetEnvIf Origin "^https://smark-web\.qa1\.smark\.swcm\.link$" CORS_ALLOW_ORIGIN=$0
SetEnvIf Origin "^https://smark-web\.qa2\.smark\.swcm\.link$" CORS_ALLOW_ORIGIN=$0

Header set Access-Control-Allow-Origin "%{CORS_ALLOW_ORIGIN}e" env=CORS_ALLOW_ORIGIN

Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type"

RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Host "id.qa2.smartwcm.swcm.link"
RequestHeader set X-Forwarded-Port "443"

# Enable the proxy module
ProxyRequests Off
ProxyPreserveHost On
# ProxyPass and ProxyPassReverse to forward requests to vmstate
ProxyPass / http://10.10.0.10:8111/
ProxyPassReverse / http://10.10.0.10:8111/

Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/id.qa2.smartwcm.swcm.link/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/id.qa2.smartwcm.swcm.link/privkey.pem


Now, let's explain each important lines:

  • ServerName id.qa1.smartwcm.swcm.link

    Specifies the primary domain for this virtual host.

  • ServerAlias id.qa2.smartwcm.swcm.link

    Specifies an alias for this virtual host. It allows the server to respond to requests with either id.qa1.smartwcm.swcm.link or id.qa2.smartwcm.swcm.link.

  • SetEnvIf Origin "^https://smark-web\.qa1\.smark\.swcm\.link$" CORS_ALLOW_ORIGIN=$0

    This Apache configuration line sets the CORS_ALLOW_ORIGIN environment variable to the value of the Origin header in incoming HTTP requests, specifically for requests with the origin "https://smark-web.qa1.smark.swcm.link," which is later used for dynamic Cross-Origin Resource Sharing (CORS) handling.

  • SetEnvIf Origin "^https://smark-web\.qa2\.smark\.swcm\.link$" CORS_ALLOW_ORIGIN=$0

    This Apache configuration line sets the CORS_ALLOW_ORIGIN environment variable to the value of the Origin header in incoming HTTP requests, specifically for requests with the origin "https://smark-web.qa2.smark.swcm.link," which is later used for dynamic Cross-Origin Resource Sharing (CORS) handling.

  • Header set Access-Control-Allow-Origin "%{CORS_ALLOW_ORIGIN}e" env=CORS_ALLOW_ORIGIN

    This Apache configuration line dynamically sets the "Access-Control-Allow-Origin" header in the HTTP response to the value of the "CORS_ALLOW_ORIGIN" environment variable only if the variable has a defined value, thereby allowing cross-origin requests based on the specified origin when the variable is set.

Post a comment