How to allow CORS for a webapp with a private endpoint?

Daan Vonk 0 Reputation points
2024-09-14T09:15:31.7533333+00:00

I'm running into an issue with CORS related to Azure Virtual Networking. I have setup an azure virtual network with three subnets:

  1. WebappFrontend, delegated to Microsoft.Web/serverfarms. Security group with only 2 custom rules, allowing inbound http and https via 80 and 443. No other configuration.
  2. WebappBackend, delegated to Microsoft.Web/serverfarms. No NSG.
  3. GeneralBackend. Here there is a private endpoint for the WebappBackend.

I made two simple Python flask apps to test, one for frontend and one for backend. Both deployed successfully to the webapps. The backend has a static API endpoint returning a standard message. The frontend has a page that sends a request using python Flask server side request, but also a request via Javascript/CORS.

These are the steps I took to identify the problem:

  • When the backend Azure Webapp is set to publicly available under networking, my frontend can reach the backend. Both via CORS as not using CORS.
  • When the backend Azure Webapp is set to private under networking, using the private endpoint, my frontend can reach the backend without using CORS. However, when using CORS I get the below error.

'403 Ip Forbidden Access'

'to fetch at 'https://al-webapp-4tg-learning-vnet-backend.azurewebsites.net/api/static' from origin 'https://al-webapp-4tg-learning-vnet-frontend.azurewebsites.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.'

I have enabled CORS under API Management settings for the backend webapp. This is also working correctly when the backend webapp is publicly available. The private endpoint also seems to work, because when the backend webapp is private the frontend can reach the normal endpoint without using CORS.

So, to me, the issue seems to lay in the virtual networking private endpoint specifically blocking a request that is using CORS. I can't find anything on how to resolve this issue. I found this related question, but there seems to be no answer https://video2.skills-academy.com/en-us/answers/questions/1189604/azure-app-service-react-app-cors-error-in-a-privat .

Thank you in advance for any help!

-------------EDIT-------------

Diving into it deeper I now learned that a CORS request uses the IP address of the machine on which the browser is running. That explains why with server-side API calls (e.g., from a Flask server within the same VNet) the calls succeeds and the CORS request gets a 403 IP forbidden.

What I learned:

  • Server-Side Requests: When your frontend server (e.g., Flask app) makes a request to the backend, it's done from within the VNet. Therefore, the backend sees the VNet's IP address or the IP address of the subnet where the frontend server is located.
  • Client-Side (CORS) Requests: When a browser makes a CORS request, the request comes from the client (user’s machine), not from the VNet. The backend sees the user's public IP address, not the IP of the VNet or the frontend server.

Now still the question remains how to solve the issue. But I thought this edit might help others.

Azure Virtual Network
Azure Virtual Network
An Azure networking service that is used to provision private networks and optionally to connect to on-premises datacenters.
2,407 questions
Azure App Service
Azure App Service
Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
7,676 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Sadaf Khan 0 Reputation points
    2024-09-15T06:39:18.8633333+00:00

    It seems you're encountering a CORS-related issue because your backend Azure Web App is set to private, and the requests made via the frontend (client-side) are coming from the user's public IP, which is being blocked due to the private endpoint configuration. Here's a potential approach to solving the problem:

    API Management with Private Endpoint Support: Since you're already using API Management, consider configuring the API Management gateway to handle requests from the frontend. This way, the gateway (which resides inside the virtual network) makes the requests to your backend, bypassing the need for the CORS request to come from the user's public IP.

    Private DNS Resolution: Ensure that the private DNS configuration for the private endpoint is resolving correctly within the virtual network. Sometimes, misconfigured DNS settings can cause issues when accessing the backend from private IPs.

    Reverse Proxy: Implement a reverse proxy within the same VNet as your frontend and backend apps. The proxy can forward the requests from the frontend to the backend, effectively bypassing the CORS issue, as the requests will be seen as internal traffic.

    Custom NSG Rules: If you want to allow CORS requests from specific IP addresses, consider updating your Network Security Group (NSG) to allow traffic from the range of IP addresses that your users might be coming from (e.g., whitelisting the public IPs of your users or the front-end).

    Hybrid Approach: A combination of enabling both public and private endpoints (for internal and external traffic) while restricting access through security policies may work. This can ensure internal traffic stays private while CORS requests can still function.

    These solutions might depend on your overall architecture, but the key here is to ensure requests made client-side (from outside your VNet) have a path to the backend, whether through a proxy, a public endpoint, or an API gateway.

    Let me know if you need more clarification or help implementing any of these ideas!

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.