I'm trying to secure an application, deployed in Azure, consisting of an Angular frontend and a Node (Nest.js) backend. I want the frontend to be accessible via the internet unlike the backend which should only be accessible from the frontend (without being accessible via the internet). The backend seems to restrict access by taking the client's IP instead of the frontend's IP which causes a 403 IP Forbidden error.
In summary (version with path to Bicep file below)
To do this, I created:
- 1 App Service for the frontend
- 1 App Service for the backend
- 1 VNet with 2 subnets:
- 1 Subnet for 1 private endpoint
- 1 Subnet for the frontend App Service
- 1 Private DNS Zone for Private Endpoint routing (created automatically when creating the Private Endpoint)
And I made the following configuration:
- App Service frontend > Networking >
- Access restriction: Allow public access
- VNet integration: added the app service to the previously created subnet
- App Service backend > Networking > Access restriction: Allow Public Access but "Deny" all "Unmatched rule action". I added a rule allowing access to the frontend subnet (Action: Allow, type: select VNet, subnet: select the subnet on which the frontend is) Like this
- App Service backend > CORS: Added frontend URL
Results
On my frontend, I make an HTTP request to my backend API. The backend responds to me ERR_FAILED 403 (Ip Forbidden). In the response headers, I see "x-ms-forbidden-ip: xxx.xxx.xx.xx" (the public ip of my company's network that my PC is on). See here. Shouldn't I see my frontend App Service IP?
For Information, if in App Service backend > Networking > Access restriction, I add a rule authorizing the public IP of my company, the request returns me a code 200 and no longer 403.
How do I block public access to the backend but still manage to perform requests from the frontend? (After many research, I haven't found any successful answers to solve this yet).
Version with Bicep file
I followed this tutorial. At the end of the article, a Bicep file is available.
So I did the following:
az group create --name SecureNTierApp --location "France Central"
az deployment group create --name DeployementSecureNTierApp --resource-group SecureNTierApp --template-file <file-name>.bicep
- Reactivate basic auth for deploy with Azure DevOps:
az resource update --resource-group SecureNTierApp --name scm --namespace Microsoft.Web --resource-type basicPublishingCredentialsPolicies --parent sites/<frontend-name> --set properties.allow=true
az resource update --resource-group SecureNTierApp --name scm --namespace Microsoft.Web --resource-type basicPublishingCredentialsPolicies --parent sites/<backend-name> --set properties.allow=true
- In Access Restrictions > Advanced tool site (on both App Service) : add a new rule (action: Allow, type: Service Tag, service tags: AzureCloud)
- App Service backend > CORS: Added frontend URL
- Note that the bicep file configures the backend > Networking > Access restriction to Allow public access: false