The role assignment is correct.

The scope is right.

Access is still denied.

Here are the hidden reasons why.

Propagation Delay Is Real

You add a role assignment. You test immediately. It fails.

Azure RBAC changes are not instant.

Propagation can take up to 30 minutes, though it is usually faster.

We spent hours debugging issues that fixed themselves while we investigated.

Now we wait five minutes before testing any new role assignment.

It is boring. But it works.

Deny Assignments Override Everything

Azure has explicit deny.

If a deny assignment exists, it overrides all allow assignments.

You can have Contributor. You can have Owner.

If there is a deny assignment, you still get “Access Denied.”

Deny assignments are rare. They are used by:

  • Azure Blueprints
  • Managed Applications
  • certain policy configurations

You cannot see deny assignments in the Azure Portal role assignments view.

You have to query them specifically:

az role assignment list --all --include-inherited --query "[?contains(principalName, 'deny')]"

We found a deny assignment blocking a Managed Identity for two days before we thought to check for it.

Resource Locks Block Even Owners

Resource locks prevent deletion and modification.

Even if you have Owner role, a CanNotDelete or ReadOnly lock will block you.

Locks are often forgotten because:

  • they are set once and never reviewed
  • they do not show up in RBAC views
  • they are inherited from parent scopes

We had a production incident where no one could update an App Service configuration.

Turns out there was a ReadOnly lock at the resource group level from a compliance initiative six months earlier.

The lock was correct. The documentation was missing.

Azure Policy Can Deny Actions

Azure Policy can enforce rules that deny operations.

Even if your RBAC allows it, policy can block it.

Common scenarios:

  • denying public IP creation
  • enforcing specific SKUs
  • requiring tags
  • blocking certain regions

The error message often does not mention policy.

It just says “Access Denied” or “Operation not allowed.”

You have to check the Activity Log to see that a policy blocked the action.

We wasted time checking RBAC when the issue was policy enforcement.

Conditional Access Affects Managed Identities Too

Conditional Access policies can block Managed Identities.

If you have policies that require:

  • MFA
  • compliant devices
  • specific locations

Managed Identities can fail those checks.

We had a Managed Identity for a Container App that stopped working.

Turns out a new Conditional Access policy required device compliance.

Managed Identities do not run on devices. They failed the check.

We had to exclude Managed Identities from that policy.

Service Principal Credentials Can Expire

If you use a service principal with a client secret, the secret expires.

When it expires, authentication fails.

The error is “Access Denied” or “Unauthorized.”

It looks like an RBAC issue. It is actually a credential issue.

We now:

  • set alerts for expiring secrets 30 days in advance
  • prefer Managed Identity to avoid credentials entirely
  • enforce certificate-based auth when secrets are unavoidable

Network Restrictions Override RBAC

Some Azure services support network restrictions:

  • Storage Accounts
  • Key Vaults
  • SQL Databases

Even if RBAC grants access, network rules can block it.

You can have Storage Blob Data Contributor. If the Storage Account only allows access from a specific VNET, your request fails.

The error is “Access Denied.”

The solution is not RBAC. It is firewall rules or private endpoints.

We learned to check network configuration before spending time on RBAC.

Subscription State Matters

If a subscription is disabled, everything in it stops working.

You cannot access resources. You cannot deploy. You cannot read.

The error is “Access Denied.”

The fix is not RBAC. It is re-enabling the subscription.

This happened to us once when a payment method failed.

We spent two hours checking RBAC before realizing the subscription was suspended.

How We Debug Access Issues Now

We built a checklist:

  1. Wait five minutes after any RBAC change.
  2. Check deny assignments:
    az role assignment list --all --include-inherited
    
  3. Check resource locks:
    az lock list --resource-group <name>
    
  4. Check Azure Policy evaluations in Activity Log.
  5. Check Conditional Access policy impact.
  6. Verify service principal credentials are not expired.
  7. Check network restrictions on the target resource.
  8. Verify subscription state.

We work through this list before assuming RBAC is wrong.

Most of the time, RBAC is correct. Something else is blocking access.

The Lesson

“Access Denied” is not always about permissions.

It can be:

  • propagation delay
  • deny assignments
  • resource locks
  • Azure Policy
  • Conditional Access
  • expired credentials
  • network restrictions
  • subscription state

RBAC is just one layer.

Now we debug the whole stack, not just the role assignments.

It is faster. It is more accurate.

And it saves us from chasing the wrong problem for hours.