The 403 error when listing Azure service principals in Terraform occurs due to insufficient permissions on your service principal. This error typically happens when upgrading Azure provider versions or when your service principal lacks required Microsoft Graph API permissions.
This error occurs when the Terraform AzureRM or AzureAD provider attempts to list service principals but receives a 403 Forbidden response from Azure. The status code 403 means the authenticated principal does not have authorization to perform this operation. This commonly happens in two scenarios: when using deprecated Azure AD Graph API (in older provider versions 1.x and 2.x) which was retired by Microsoft, or when your service principal lacks the required Microsoft Graph API permissions like Group.Read.All and Directory.Read.All.
Update your Terraform configuration to use the latest AzureRM provider which uses Microsoft Graph API instead of the deprecated Azure AD Graph API:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {}
}Then run:
terraform init
terraform planNavigate to your Azure portal and grant the service principal the required permissions:
1. Go to Azure AD > App registrations > Select your app
2. Click "API permissions" in the left sidebar
3. Click "Add a permission"
4. Select "Microsoft Graph"
5. Choose "Application permissions"
6. Search for and select:
- Directory.Read.All
- Group.Read.All
- Application.ReadWrite.All (if managing applications)
7. Click "Add permissions"
The permissions must be granted by a tenant administrator:
1. Stay on the "API permissions" page
2. Look for the blue button "Grant admin consent for [TenantName]"
3. Click this button
4. Confirm the consent dialog
5. Wait a few moments for the consent to take effect
After granting consent, the permissions should show "Granted for [TenantName]".
Decode your service principal token to verify permissions are included:
# Get an access token (using Azure CLI with service principal)
az account get-access-token --query accessToken -o tsv
# Decode the token at https://jwt.msFor service principal authentication, check the "roles" claim. For delegated authentication, check the "scp" claim. Both should include the permissions you granted.
Run Terraform with the updated configuration:
terraform init
terraform plan
terraform applyThe 403 error should no longer appear as your service principal now has the required permissions and the provider uses Microsoft Graph API.
If you're still experiencing issues, verify the correct permission type:
- Service Principal (Application): Requires Application permissions (not Delegated)
- User-based access: Requires Delegated permissions
In your Terraform service principal scenario, you need Application permissions. Ensure under "API permissions" you selected "Application permissions" and not "Delegated permissions".
The Azure AD Graph API retirement timeline: deprecated since September 1, 2024, with full retirement scheduled for July 1, 2025. All new applications are blocked from accessing Azure AD Graph since February 1, 2025. If you cannot upgrade immediately, you may need to temporarily use Azure CLI or PowerShell with the service principal instead of Terraform. In CI/CD pipelines, ensure the service principal executing Terraform has these permissions in all environments (dev, staging, production). Some organizations restrict Application.ReadWrite.All; if so, discuss with your Azure administrator about using Application.ReadWrite.OwnedBy which only manages applications the service principal owns. For Cloud Shell environments, note that ARM_SUBSCRIPTION_ID and ARM_TENANT_ID environment variables may be overwritten - verify these match your intended service principal.
Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform