How To
ForgeRock Identity Platform
Does not apply to Identity Cloud

How do I troubleshoot issues with CORS in AM (All versions)?

Last updated Jan 16, 2023

The purpose of this article is to provide pointers on how to troubleshoot and resolve issues with Cross-origin resource sharing (CORS) in AM.


2 readers recommend this article

Troubleshooting techniques

You should use the following approach to troubleshoot issues with CORS:

  1. Check that all headers included in the CORS request have been allowlisted otherwise the browser will block the request. You can allowlist the headers by ensuring they are included in the Access-Control-Allow-Headers header. See Configure CORS support (AM 7 and later) or Enabling CORS Support (AM 6.x) for further information.
  2. Make a direct curl call to the required endpoint to check that the CORS request headers come back as expected. This will help you verify that CORS is set up correctly for a particular endpoint. See Check CORS is set up correctly for an endpoint for examples.
  3. Set debug logging level to Message or Warning level, and grep for "WARNING: CORS Fail" in the CoreSystem log. Then find the corresponding section in this article to resolve your issue. You can enable message level debugging as described in Debug logging (AM 7 and later) or How do I enable Message level debugging in AM 6.x debug files? (AM 6.x).
  4. Obtain an HTTP Trace of the failing flow in your browser. You can do this by capturing a HAR file as described in How do I create a HAR file for troubleshooting AM?
    • If the issue happens in some browsers (for example, Chrome™), but not in others (for example, Firefox®), obtain an HTTP Trace from the working flow to allow comparison.
Note

As of AM 7, you should configure CORS via the UI or the /global-config/services/CorsService REST endpoint (Configure CORS support); configuring CORS using the web.xml file is only available in AM 6.x (Enabling CORS Support).

The following issues are detailed in this article:

Check CORS is set up correctly for an endpoint

You can check that CORS is set up correctly for a particular endpoint by making a direct curl call. The following examples show a working setup versus a couple of non-working setups for comparison.

Working setup 

This example demonstrates a working setup, where a direct call to the authenticate endpoint brings back all the expected CORS response headers.

Example call: $ curl -v -X OPTIONS -H "Origin: http://other.origin.example.com" -H "Access-Control-Request-Method: POST" -H "Access-Control-Request-Headers: X-Requested-With" https://am.example.com:8443/am/json/authenticate

Example response:* About to connect() to am.example.com port 8443 (#0) * Trying 198.51.100.0... * Connected to am.example.com (198.51.100.0) port 8443 (#0) > OPTIONS /am/json/authenticate HTTP/1.1 > User-Agent: curl/7.29.0 > Host: am.example.com:8443 > Accept: */* > Origin: http://other.origin.example.com > Access-Control-Request-Method: POST > Access-Control-Request-Headers: X-Requested-With > < HTTP/1.1 200 OK HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 Server: Apache-Coyote/1.1 < X-Frame-Options: SAMEORIGIN X-Frame-Options: SAMEORIGIN < Access-Control-Allow-Methods: POST,PUT,GET,DELETE,OPTIONS Access-Control-Allow-Methods: POST,PUT,GET,DELETE,OPTIONS < Access-Control-Allow-Headers: cookie,origin,accept,x-requested-with,authorization,accept-api-version,origin,accept,x-requested-with,content-type,access-control-request-method,access-control-request-headers,authorization,content-type,iplanetdirectorypro,x-openam-username,x-openam-password,accept,accept-encoding,connection,content-length,host,origin,user-agent,accept-language,referer,dnt,accept-api-version,if-none-match Access-Control-Allow-Headers: cookie,origin,accept,x-requested-with,authorization,accept-api-version,origin,accept,x-requested-with,content-type,access-control-request-method,access-control-request-headers,authorization,content-type,iplanetdirectorypro,x-openam-username,x-openam-password,accept,accept-encoding,connection,content-length,host,origin,user-agent,accept-language,referer,dnt,accept-api-version,if-none-match < Access-Control-Max-Age: 600 Access-Control-Max-Age: 600 < Access-Control-Allow-Origin: http://other.origin.example.com Access-Control-Allow-Origin: http://other.origin.example.com < Content-Length: 0 Content-Length: 0 < Date: Wed, 23 Mar 2022 16:29:14 GMT Date: Wed, 23 Mar 2022 16:29:14 GMT < * Connection #0 to host am.example.com left intact

Non-working setup 

This example demonstrates a non-working setup, where a direct curl call to the authenticate endpoint results in a 501: Not Implemented response.

Example call: $ curl -v -X OPTIONS -H "Origin: http://other.origin.example.com" -H "Access-Control-Request-Method: OPTIONS" -H "Access-Control-Request-Headers: X-Requested-With" https://am.example.com:8443/am/json/authenticate

Example response: * About to connect() to am.example.com port 8443 (#0) * Trying 198.51.100.0... * Connected to am.example.com (198.51.100.0) port 8443 (#0) > OPTIONS /am/json/authenticate HTTP/1.1 > User-Agent: curl/7.29.0 > Host: am.example.com:8443 > Accept: */* > Origin: http://other.origin.example.com > Access-Control-Request-Method: OPTIONS > Access-Control-Request-Headers: X-Requested-With > < HTTP/1.1 405 < Date: Mon, 21 Mar 2022 11:32:04 GMT < Content-Type: application/json;charset=UTF-8 < Content-Length: 67 < Connection: keep-alive < Set-Cookie: iPlanetDirectoryPro=AQIC5wM2LY4SfcxsuvGEjcsppDSFR8H8DYBSouTtz3m64PI.*AAJTSQACMDIAAlNLABQtNTQwMTU3NzgxODI0NzE3OTIwNAEwNDU2NjE0*; Expires=Mon, 21 Mar 2022 11:32:04 GMT; Path=/; SameSite=None; Secure < X-Frame-Options: SAMEORIGIN < Content-API-Version: resource=2.1 < * Connection #0 to host am.example.com left intact {"code":501,"reason":"Not Implemented","message":"Not Implemented"}

This response indicates a misconfiguration issue, where the details in the curl command do not match what has been specified in the CORS configuration. This can be something as simple as a typo in one of the headers or a mismatch between details in the curl command and the configuration. You should check your curl command and the CORS configuration for any discrepancies. See Configure CORS support (AM 7 and later) or Enabling CORS Support (AM 6.x) for further information.

Common mismatches to check for are: 

  • The Origin specified in the curl call does not exactly match one of the acceptedOrigins (origins) in the CORS configuration, including ports. You should check the CORS configuration, for example:
    • REST (AM 7 and later):{    "acceptedOrigins": [         "http://other.origin.example.com",         "http://another.origin.com:8080"     ] }
    • web.xml file (AM 6.x):<param-name>origins</param-name> <param-value>http://other.origin.example.com,http://another.origin.com:8080</param-value>
  • AM 6.x: The Access-Control-Request-Headers specified in the curl call includes a header, which is not allowed in the CORS configuration. You should check the cors.allowed.headers section in the web.xml file, for example:<param-name>cors.allowed.headers</param-name> <param-value>Authorization,Content-Type,X-Requested-With,...</param-value>

Non-working setup (OAuth 2.0) 

This example demonstrates a non-working setup, where a direct call to the oauth2/authorize endpoint fails to bring back the expected CORS response headers.

Example call: $ curl -v -X OPTIONS -H "Origin: http://other.origin.example.com" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-Requested-With" https://am.example.com:8443/am/oauth2/authorize

Example response:* About to connect() to am.example.com port 8443 (#0) * Trying 198.51.100.0... * Connected to am.example.com (198.51.100.0) port 8443 (#0) > OPTIONS /am/oauth2/authorize HTTP/1.1 > User-Agent: curl/7.29.0 > Host: am.example.com:8443 > Accept: */* > Origin: http://other.origin.example.com > Access-Control-Request-Method: GET > Access-Control-Request-Headers: X-Requested-With > < HTTP/1.1 405 Method Not Allowed HTTP/1.1 405 Method Not Allowed < Server: Apache-Coyote/1.1 Server: Apache-Coyote/1.1 < X-Frame-Options: SAMEORIGIN X-Frame-Options: SAMEORIGIN < Pragma: no-cache Pragma: no-cache < Cache-Control: no-store Cache-Control: no-store < Date: Wed, 23 Mar 2022 16:33:27 GMT Date: Wed, 23 Mar 2022 16:33:27 GMT < Accept-Ranges: bytes Accept-Ranges: bytes < Content-Type: application/json Content-Type: application/json < Transfer-Encoding: chunked Transfer-Encoding: chunked < * Connection #0 to host am.example.com left intact {"error_description":"Required Method: GET or POST found: OPTIONS","error":"method_not_allowed"}

This response indicates that CORS support is not enabled for OAuth 2.0 flows. This can be resolved as follows:

  • AM 7 and later: Check the CORS filter is enabled: Configure CORS support.
  • AM 6.x: Add oauth2 to the CORSFilter filter-mapping in the web.xml, for example:<filter-mapping>        <filter-name>CORSFilter</filter-name>         <url-pattern>/json/*</url-pattern>         <url-pattern>/oauth2/*</url-pattern>     </filter-mapping>

Issue with the Origin

The following warning is displayed in the CoreSystem log: WARNING: CORS Fail - Requested origin comes from a location not whitelisted.

Troubleshooting

In the HTTP trace, search for a request that contains an Origin Header such as the following; the value of the header indicates where the cross-origin request or Preflight request originates from. Origin:http://other.origin.example.com:8080

The response to such a request should contain the required Access-Control-Allow-Origin header such as the following; the value (URLs) indicates what origins are allowed when making a CORS request to access the resource. Access-Control-Allow-Origin:http://other.origin.example.com:8080

Solution

  1. If the Response does not contain this header, check the acceptedOrigins (origins) in the CORS configuration for this value (http://other.origin.example.com:8080 in the above example).
  2. Add the missing origin to the configuration accordingly. You need to add the exact same value that is displayed in the Origin header of the request. For example:
    • REST (AM 7 and later):{    "acceptedOrigins": [         "https://am.example.com:8443",         "https://lb.example.com:443",         "http://www.example.org:80",         "http://other.origin.example.com:8080"     ] }
    • web.xml file (AM 6.x): <init-param>     <description>          Accepted Origins (Required):          A comma separated list of origins from which to accept CORS requests.      </description>      <param-name>origins</param-name>      <param-value>          https://am.example.com:8443,https://lb.example.com:443,http://www.example.org:80,http://other.origin.example.com:8080      </param-value> </init-param>
  3. AM 6.x: Restart the web application container in which AM runs.
  4. Re-test the failing flow.

Issue with the Method

The following warning is displayed in the CoreSystem log: WARNING: CORS Fail - Requested HTTP method has not been whitelisted.

Troubleshooting

In the HTTP trace, search for a request that contains an Origin Header, such as: Origin:http://other.origin.example.com:8080

Find the corresponding HTTP method in the CORS requests to AM.

In the following example, the method is POST:>Connected to am.example.com (192.168.57.6) port 8443 (#0) > POST /am/json/authenticate HTTP/1.1 > Host: am.example.com:8443 > User-Agent: curl/7.43.0 > Accept: */* > cache-control: no-cache > content-type: application/json > Origin: http://other.origin.example.com:8080

Solution

  1. Check the acceptedMethods (methods) in the CORS configuration for each method highlighted above (POST in the above example).
  2. Add the missing methods to the configuration accordingly:
    • REST (AM 7 and later):{    "acceptedMethods": [         "POST",         "PUT",     ] }
    • web.xml file (AM 6.x): <init-param>    <description>         Accepted Methods (Required):         A comma separated list of HTTP methods for which to accept CORS requests.     </description>     <param-name>methods</param-name>     <param-value>POST,PUT</param-value> </init-param>
  3. AM 6.x: Restart the web application container in which AM runs.
  4. Re-test the failing flow.

Issue with Request Headers

The following error can happen with Preflight requests. Such requests use the OPTIONS method: WARNING: CORS Fail - Preflight request contained the Access-Control-Request-Headers headers with an invalid value.

Note

The OPTIONS method does not need to be added as an Accepted Method in the filter as it is accepted by default.

Troubleshooting

In the HTTP trace, search for a request that contains an Access Control Request Headers such as the following; this header is issued during the preflight request to indicate which HTTP headers will be used when the actual request is made. Access-Control-Request-Headers:<header-name>, <header-name>, ...

The response to this preflight request should include the required Access-Control-Allow-Headers response header containing the header names that can be used in the actual request: Access-Control-Allow-Headers:<header-name>, <header-name>, ...

If there is no header match, the preflight will fail and you will not see the Access-Control-Allow-Headers.

Solution  

  1. If the Response does not contain the requested header, check the acceptedHeaders (headers) in the CORS configuration.
  2. Add the missing header to this section accordingly, for example:
    • REST (AM 7 and later):{    "acceptedHeaders": [         "iPlanetDirectoryPro",         "X-OpenAM-Username",         "X-OpenAM-Password",         "Accept-API-Version",         "Content-Type",         "If-Match",         "If-None-Match"     ] }
    • web.xml file (AM 6.x):<init-param>   <description>        Allowed Headers (Optional):        A comma separated list of HTTP headers which can be included in the requests.    </description>    <param-name>headers</param-name>    <param-value>iPlanetDirectoryPro,X-OpenAM-Username,X-OpenAM-Password,Accept-API-Version,Content-Type,If-Match,If-None-Match</param-value> </init-param>
  3. AM 6.x: Restart the web application container in which AM runs.
  4. Re-test the failing flow.

Issue with the hostname (AM 6.x)

The following warning is displayed in the CoreSystem log: WARNING: CORS Fail - Expected hostname does not equal actual hostname.

Troubleshooting

In the HTTP trace, search for a request that contains an Origin Header, such as: Origin:http://other.origin.example.com:8080

In the same request, check the Host header; the host is the domain the request is being sent to. Host: am.example.com:8443

Solution

  1. The exact hostname must be present in the CORS filter in the web.xml file, in the Expected Hostname section: <init-param>   <description>        Expected Hostname (Optional):        The name of the host expected in the request Host header.    </description>    <param-name>expectedHostname</param-name>    <param-value>https://am.example.com:8443</param-value> </init-param>
  2. Remove or comment out the Expected Hostname section in the CORS filter if you need more than one hostname (for example, if you use a load balancer) as AM does not accept lists of Expected Hostnames.
  3. Restart the web application container in which AM runs.
  4. Re-test the failing flow.

Issue with 302 returned on /UI/Login URL (AM 6.x)

The redirect to the login page fails; you get a 302 response for an OPTIONS request (Preflight request) when attempting to access a /UI/Login URL. This scenario typically occurs when you have a web agent configured in your deployment.

The following error is shown in the console logs: Response for preflight is invalid (redirect)

Troubleshooting

The browser does not accept an HTTP 302 redirect as a response to a Preflight request, which is why you see the console error.

When you attempt to access the /UI/Login URL, AM tries to redirect you to the XUI equivalent ( /XUI/#login) based on the XUIFilter filter-mapping. If a Web Agent is used where the old /UI/Login (login URL) is used to generate the OAuth 2.0 based login then the ordering matters as the CORS request may not be handled.

Solution

  1. Move the CORSFilter filter-mapping in the web.xml file to just before the XUIFilter filter-mapping, for example: <filter-mapping>        <filter-name>CORSFilter</filter-name>         <url-pattern>/*</url-pattern>     </filter-mapping>   <filter-mapping>     <filter-name>XUIFilter</filter-name>
  2. Restart the web application container in which AM runs.
  3. Re-test the failing flow.

See Also

Login page in AM 6.x hangs on Loading when CORS is enabled

SameSite cookie support in AM and IG

Configure CORS support

About IG as an UMA resource server

Related Training

N/A

Related Issue Tracker IDs

OPENAM-19177 (Clarify Change to CORS filter in AM 7 upgrades)

OPENAM-11863 (CORSFilter position in web.xml should come before most filters)

OPENAM-9890 (Allow list in expected Hostname section of CORS Filter)

OPENAM-8811 (allow wildcarding for origins in CORSFilter)

OPENAM-5984 (The XUI is unhappy when the CORS filter is enabled)


Copyright and Trademarks Copyright © 2023 ForgeRock, all rights reserved.