Cross-Origin Resource Sharing (CORS) controls which web applications can make requests to ServiceControl. This is important when ServicePulse is hosted on a different domain or port than ServiceControl.
Configuration
ServiceControl instances can be configured via environment variables or App.config. Each instance type uses a different prefix. See the Hosting Guide for example usage of these configuration settings in conjunction with Authentication, TLS, and Forward Headers configuration settings in a scenario based format.
When to configure CORS
CORS configuration is required when:
- ServicePulse is hosted on a different domain than ServiceControl
- ServiceControl is accessed through a reverse proxy with a different domain
CORS configuration is not required when:
- ServicePulse is hosted by ServiceControl, for calls to the Error instance that hosts it. Integrated ServicePulse requests that instance's API on the same origin, using the root-relative URL
/.api/ - ServicePulse is using the internal reverse proxy, which forwards both the Error instance API and the Monitoring instance API through the ServicePulse origin.
Unless it is reached through one of the reverse proxies above, a ServiceControl Monitoring instance listens on its own port, so it is a separate origin from ServicePulse even when both run on the same machine. This includes integrated ServicePulse, which shares an origin with the Error instance hosting it but not with the Monitoring instance. These cross-origin requests are allowed by default, because Cors. defaults to true. When origins are restricted, as recommended for production, the ServicePulse origin must be added to Monitoring/ as well as to the Error instance. For a worked example, see making ServiceControl Monitoring reachable.
Configuration examples
To restrict access to only your ServicePulse domain, using the primary ServiceControl instance:
<appSettings>
<add key="ServiceControl/Cors.AllowAnyOrigin" value="false" />
<add key="ServiceControl/Cors.AllowedOrigins" value="https://servicepulse.yourcompany.com" />
</appSettings>
To allow multiple origins:
<appSettings>
<add key="ServiceControl/Cors.AllowAnyOrigin" value="false" />
<add key="ServiceControl/Cors.AllowedOrigins" value="https://servicepulse.yourcompany.com,https://admin.yourcompany.com" />
</appSettings>
Troubleshooting
ServicePulse cannot connect to ServiceControl
Symptom: ServicePulse displays connection errors or fails to load data, and browser developer tools show CORS errors like "Access-Control-Allow-Origin" or "blocked by CORS policy".
Cause: The ServicePulse origin is not in the allowed origins list, or the origin URL doesn't match exactly (including protocol and port).
Solutions:
- Check browser developer tools (F12 > Console) for the exact CORS error message
- Verify the origin in
AllowedOriginsmatches exactly, including:- Protocol (
https:/vs/ http:/)/ - Domain name (no trailing slash)
- Port number if non-standard (e.g.
https:/)/ servicepulse. example. com:8080
- Protocol (
- For testing, temporarily set
AllowAnyOrigintotrueto confirm CORS is the issue.
Do not leave AllowAnyOrigin set to true in any production environment. This removes a key browser security feature.
CORS preflight requests failing
Symptom: Simple GET requests work, but POST/PUT/DELETE requests fail with CORS errors. Browser shows OPTIONS request failures.
Cause: The browser sends a preflight OPTIONS request for complex requests, which may be blocked by a firewall or reverse proxy.
Solutions:
- Ensure the reverse proxy forwards OPTIONS requests to ServiceControl
- Check that no firewall or WAF is blocking OPTIONS requests
- Verify ServiceControl is responding to OPTIONS requests (check response headers)
Origin mismatch with reverse proxy
Symptom: CORS errors occur even though the origin appears to be configured correctly.
Cause: When using a reverse proxy, the origin seen by ServiceControl may differ from what's configured. The browser sends the origin based on where ServicePulse is loaded from.
Solutions:
- Check which URL the browser is using to access ServicePulse (this is the origin)
- Ensure the configured origin matches the ServicePulse URL exactly
- If using different domains for internal and external access, add both origins to
AllowedOrigins
Credentials not being sent
Symptom: Authenticated requests fail even when CORS is configured. The Authorization header is not sent.
Cause: When using authentication with CORS, credentials are only sent if the response includes appropriate CORS headers and the origin is explicitly allowed (not wildcard).
Solutions:
- Ensure
AllowAnyOriginis set tofalsewhen using authentication - Add the specific origin to
AllowedOrigins(wildcards don't support credentials) - Verify the
Access-Control-Allow-Credentialsheader is present in responses