The Azure Functions runtime is failing to allow cross-origin requests because the CORS configuration is either missing, malformed, or overly restrictive.
The most common culprit is that the Host.json file, which controls global function app settings including CORS, is either absent or doesn’t contain the cors section at all. This means no origins are explicitly allowed, and by default, Azure Functions doesn’t permit any cross-origin requests for security reasons.
Diagnosis: Check the Host.json file in your Azure Functions project’s root directory. If it’s missing, or if it exists but lacks a cors array, you’ve found your problem.
Fix: Add or modify the cors section in your Host.json file. To allow all origins (useful for development, but be cautious in production), use:
{
"version": "2.0",
"cors": {
"allowedOrigins": [ "*" ]
}
}
This tells the Azure Functions host to respond to any incoming request with Access-Control-Allow-Origin: *, effectively allowing any domain to make requests to your functions.
A very common scenario is allowing a specific frontend domain. For example, if your frontend is hosted on https://my-frontend.azurewebsites.net, you’d configure CORS like this:
{
"version": "2.0",
"cors": {
"allowedOrigins": [ "https://my-frontend.azurewebsites.net" ]
}
}
This limits access to only that specific origin, providing better security.
Sometimes, the allowedOrigins array is present but contains incorrect values. This can happen if you’ve copied a configuration and forgotten to update the domain, or if you’re using different environments (dev, staging, prod) and haven’t mapped them correctly.
Diagnosis: Carefully review the exact strings within the allowedOrigins array. Ensure there are no typos, missing protocols (http:// or https://), or trailing slashes that don’t match your frontend’s actual origin.
Fix: Correct any inaccuracies in the allowedOrigins list. For instance, if your frontend is served from http://localhost:3000 during local development, ensure that exact string is present:
{
"version": "2.0",
"cors": {
"allowedOrigins": [ "http://localhost:3000" ]
}
}
This works because the Azure Functions host inspects the Origin header of incoming requests and, if it matches an entry in allowedOrigins, it includes the corresponding Access-Control-Allow-Origin header in its response.
Another frequent issue is forgetting to include https:// or http:// in the allowed origins, or conversely, including it when the request is made without it. The Origin header is a precise string.
Diagnosis: Check the browser’s developer console network tab for the failing request. Look at the Origin header sent by the browser and compare it meticulously to your allowedOrigins configuration.
Fix: Ensure the allowedOrigins array precisely matches the Origin header, including the protocol. If your frontend is on https://localhost:3000, use that. If it’s http://localhost:3000, use that.
{
"version": "2.0",
"cors": {
"allowedOrigins": [ "https://localhost:3000" ]
}
}
This ensures the exact string match required for the CORS handshake to succeed.
It’s also possible to have multiple origins allowed, but the syntax might be incorrect. For example, an array containing a single string that itself contains multiple comma-separated origins is invalid.
Diagnosis: Examine the allowedOrigins array structure. It should be a JSON array of strings, where each string is a single origin.
Fix: Ensure each allowed origin is a distinct element in the array:
{
"version": "2.0",
"cors": {
"allowedOrigins": [
"https://my-frontend.azurewebsites.net",
"https://staging.my-frontend.azurewebsites.net",
"http://localhost:3000"
]
}
}
This correctly lists each origin as a separate, valid entry that the host can check against.
A less common but still relevant issue is the presence of other global settings in Host.json that might interfere, or simply an outdated Host.json schema version. Azure Functions supports different version values, and the cors configuration syntax might vary slightly.
Diagnosis: Verify your Host.json starts with "version": "2.0". If it’s an older version (e.g., "1.0"), you’ll need to update it.
Fix: Ensure your Host.json has the correct version and structure:
{
"version": "2.0",
"cors": {
"allowedOrigins": [ "*" ]
},
"extensions": {
"http": {
"routePrefix": "api"
}
}
}
This explicitly sets the schema version and then includes the CORS configuration, ensuring compatibility with the current Azure Functions runtime.
Finally, in some very specific deployment scenarios, especially with custom domains or complex network configurations, the Function App might not be correctly registered or accessible to receive the CORS headers. This is rare for typical deployments but can occur.
Diagnosis: Verify your Function App is deployed and accessible via its default .azurewebsites.net hostname. Check network security groups or firewalls if you suspect external network issues.
Fix: Re-deploy your Function App. If using custom domains, ensure the DNS is correctly resolving and the SSL certificate is valid. This forces a refresh of the app’s configuration and network presence.
After fixing your CORS issues, the next error you might encounter is related to missing authorization checks if your functions are not intended for public access.