API servers should not allow any origin for CORS
ExpressJS and NET server are both setting CORS to allow any origin, which is a security vulnerability.
CORS allow origins should be set during provisioning to allow only client's origin, azure portal, or localhost+debug-port


@hemarina has been doing some great work here and has a possible approach, but we are running into some issues.
While some services, Like App Service, can handle CORS on your behalf (we use this today: https://github.com/Azure-Samples/todo-nodejs-mongo/blob/59daadf7e1a764f3109f46809055ccc5f8ac9dd3/infra/resources.bicep#L25, which ends up setting the cors setting for the actual AppService App we create). Others, Like Azure Container Apps do not have native support for CORS.
Because of this - we'll continue to need to have the API service handle CORS itself. To configure CORS correctly, we need to ensure that the API service has the hostname of the web app, so it can include it in the list of allowed origins. Since we can't know this information at development time of the service, we have to take this value as "configuration" for the API service, so we could do something like this:
app.use(cors({
origin: [
"http://localhost:3000",
"https://portal.azure.com",
"https://ms.portal.azure.com",
process.env.WEB_ORIGIN
]
});
For ACA, to ensure that WEB_ORIGIN is set, we need to add an entry to the env property of the template for the container app.
This leads to a slight problem - because the web service itself needs the hostname of the api service (so it can correctly generate the config json file that is used for the XHR requests the SPA has to make to the API). Since we have to create the container app in order to get the hostname, we run into an issue where we need the API Hostname to create the Web Container App, and we need the Web Hostname to create the API Container App, which leads to a circular dependency.
For ACA, I suspect we can come up with a solution by exploiting the fact that outputs are written to the .env file and you can use them in the .parameters.json file, coupled with the fact that deploy actually does an arm deployment, which gives us a chance to update the env settings in the resource, but we might need some slight refactoring in the bicep modules.
@wbreza I suspect things would be largely the same for AKS and whatever tricks we play for ACA will probably translate over, but I wanted to tag you on the issue to bring it to your attention, so it's something you can start mulling over.
coupled with the fact that deploy actually does an arm deployment, which gives us a chance to update the env settings in the resource, but we might need some slight refactoring in the bicep modules.
I would not make the CORS settings depend on running provisioing + deploy.
Can we, instead, add an extra step at the end of provisioing designed to set-up anything like this? A step which is not related to a provisioning-provider (bicep, terraform, etc). We would expect resources already deployed and we would just update the env to set the config.
-- Optionally, we could consider removing the ingress from the api service
That would only make it reachable from the web service (from the same container environment).
This might be a more secured solution to recommend for customers
Can we, instead, add an extra step at the end of provisioing designed to set-up anything like this? A step which is not related to a provisioning-provider (bicep, terraform, etc). We would expect resources already deployed and we would just update the env to set the config.
This is something we could explore, but I'm not 100% sure what the logic would end up looking like. How would an application denote what happens during this post processing step?
-- Optionally, we could consider removing the ingress from the api service That would only make it reachable from the web service (from the same container environment).
This might be a more secured solution to recommend for customers
Unsure this works - the API service has to be accessible on the public internet, right? The calls from the SPA come from the end user's browser...
@hemarina can you update on the progress?