You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SharePoint Embedded: container type registration grants can take hours to propagate, and the 403 is indistinguishable from a permanent misconfiguration #10972
Corrected. The managed-identity root cause below is wrong — see the correction comment. The managed identity works; the grant simply took 1–2.5 hours to propagate. The real issue is that a bare 403 accessDenied cannot be told apart from a permanent misconfiguration during that window. Original text kept below for the record.
Troubleshooting — the "Access denied when calling container or file APIs" row
Summary
I built a SharePoint Embedded app hosted on Azure Container Apps and tried to
use its user-assigned managed identity for app-only access, since that means
the app holds no credential at all. Every requirement the documentation states
was satisfied and verified, and the call failed with a bare 403 accessDenied
giving no indication of which layer refused.
A controlled comparison shows that an Azure managed identity is refused where
an ordinary Entra app registration with identical permissions succeeds. The
documentation never mentions managed identities — it neither supports nor rules
them out — so there was no way to know this short of testing it.
What the docs currently say
"Configure app-only token acquisition":
Configure an application credential, such as a certificate.
Have a consuming tenant administrator grant admin consent.
Acquire a token using the client credentials flow.
"such as a certificate" reads as an example, not a constraint.
"Plan authentication and permissions":
The owning app must have a service principal installed on the consuming tenant.
A managed identity is a service principal, so this reads as satisfied.
Searching the SharePoint Embedded doc set for "managed identity" returns
nothing at all.
The controlled comparison
Three callers, same tenant, same container type, same request. All three held
Graph application role FileStorageContainer.Selected (verified present in the
issued token's roles claim) and all three were granted applicationPermissions: ["full"] in the same container type registration:
Caller
Identity type
Owns the container type
roles in token
Result
Owning app, certificate
App registration
Yes
FileStorageContainer.Selected
200 OK
Guest app, certificate
App registration
No
FileStorageContainer.Selected
200 OK
User-assigned managed identity
Managed identity
No
FileStorageContainer.Selected
403 accessDenied
The guest app registration rules out container type ownership as the cause: a
non-owning app registration works fine. The only remaining difference is the
identity type — servicePrincipalType: ManagedIdentity versus Application.
The request:
GET https://graph.microsoft.com/v1.0/storage/fileStorage/containers?$filter=containerTypeId eq {containerTypeId}
A second finding, which made this much harder to diagnose
When I first granted the guest app registration, it returned the exact same
bare 403 accessDenied. It began working roughly three minutes later with no
change on my side — the container type registration grant simply hadn't
propagated yet.
So the identical error means both:
"this will start working shortly, wait", and
"this will never work, the caller type is unsupported"
with nothing in the response to tell them apart. During the propagation window
I had a false negative that looked exactly like the permanent failure. Anyone
testing a new grant can easily conclude their setup is wrong when it's simply
not ready, or conclude they need to wait when in fact they need a different
credential type.
Why the current troubleshooting entry doesn't help
Access denied when calling container or file APIs. — Likely cause: the
container type hasn't been registered in the consuming tenant, or the
application lacks container type application permissions.
Both listed causes were verified as not applicable. The row offers nothing
further, so following it leads to re-checking two things that are already
correct.
Suggested changes
State that managed identities aren't supported callers, on "Configure
app-only token acquisition". One sentence would have saved a lot of time:
App-only access requires an Entra ID application registration with a
certificate or client secret. Azure managed identities aren't supported as
SharePoint Embedded callers.
This matters because a managed identity is the credential-free option, and is
what Azure guidance steers you toward everywhere else — so it's a natural
first choice for an app hosted on Azure, and the one that silently fails.
Document the propagation delay on container type registration. Something
like: "Grants can take several minutes to take effect. During this window,
calls return 403 accessDenied. Retry before concluding the grant is wrong."
Add a Troubleshooting row for when everything checks out:
Access denied on container APIs after confirming registration and
container type permissions. — Likely cause: the grant hasn't propagated
yet, or the caller isn't a supported identity type. Retry after several
minutes; if it persists, confirm the caller is an app registration rather
than a managed identity.
Distinguish the causes in the error (a product ask, not a docs one, but
it's the root of the cost). accessDenied with an empty innerError is
currently identical across at least five distinct situations: missing Graph
role, missing admin consent, unregistered container type, unpropagated grant,
and unsupported caller type. Naming which layer refused — even just "Graph
permission" versus "container type permission" — would remove nearly all of
the guesswork here.
Environment
Microsoft Graph v1.0, /storage/fileStorage/containers
Trial container type, developer tenant
Failing caller: user-assigned managed identity on Azure Container Apps, token
from the platform identity endpoint with an explicit client_id
Working callers: two Entra app registrations (one owning the container type,
one not), both using certificate credentials and the client credentials flow
Important
Corrected. The managed-identity root cause below is wrong — see the correction comment. The managed identity works; the grant simply took 1–2.5 hours to propagate. The real issue is that a bare
403 accessDeniedcannot be told apart from a permanent misconfiguration during that window. Original text kept below for the record.Pages this affects
Summary
I built a SharePoint Embedded app hosted on Azure Container Apps and tried to
use its user-assigned managed identity for app-only access, since that means
the app holds no credential at all. Every requirement the documentation states
was satisfied and verified, and the call failed with a bare
403 accessDeniedgiving no indication of which layer refused.
A controlled comparison shows that an Azure managed identity is refused where
an ordinary Entra app registration with identical permissions succeeds. The
documentation never mentions managed identities — it neither supports nor rules
them out — so there was no way to know this short of testing it.
What the docs currently say
"Configure app-only token acquisition":
"such as a certificate" reads as an example, not a constraint.
"Plan authentication and permissions":
A managed identity is a service principal, so this reads as satisfied.
Searching the SharePoint Embedded doc set for "managed identity" returns
nothing at all.
The controlled comparison
Three callers, same tenant, same container type, same request. All three held
Graph application role
FileStorageContainer.Selected(verified present in theissued token's
rolesclaim) and all three were grantedapplicationPermissions: ["full"]in the same container type registration:rolesin tokenFileStorageContainer.SelectedFileStorageContainer.SelectedFileStorageContainer.SelectedThe guest app registration rules out container type ownership as the cause: a
non-owning app registration works fine. The only remaining difference is the
identity type —
servicePrincipalType: ManagedIdentityversusApplication.The request:
The managed identity's response:
A second finding, which made this much harder to diagnose
When I first granted the guest app registration, it returned the exact same
bare
403 accessDenied. It began working roughly three minutes later with nochange on my side — the container type registration grant simply hadn't
propagated yet.
So the identical error means both:
with nothing in the response to tell them apart. During the propagation window
I had a false negative that looked exactly like the permanent failure. Anyone
testing a new grant can easily conclude their setup is wrong when it's simply
not ready, or conclude they need to wait when in fact they need a different
credential type.
Why the current troubleshooting entry doesn't help
Both listed causes were verified as not applicable. The row offers nothing
further, so following it leads to re-checking two things that are already
correct.
Suggested changes
State that managed identities aren't supported callers, on "Configure
app-only token acquisition". One sentence would have saved a lot of time:
This matters because a managed identity is the credential-free option, and is
what Azure guidance steers you toward everywhere else — so it's a natural
first choice for an app hosted on Azure, and the one that silently fails.
Document the propagation delay on container type registration. Something
like: "Grants can take several minutes to take effect. During this window,
calls return
403 accessDenied. Retry before concluding the grant is wrong."Add a Troubleshooting row for when everything checks out:
Distinguish the causes in the error (a product ask, not a docs one, but
it's the root of the cost).
accessDeniedwith an emptyinnerErroriscurrently identical across at least five distinct situations: missing Graph
role, missing admin consent, unregistered container type, unpropagated grant,
and unsupported caller type. Naming which layer refused — even just "Graph
permission" versus "container type permission" — would remove nearly all of
the guesswork here.
Environment
v1.0,/storage/fileStorage/containersfrom the platform identity endpoint with an explicit
client_idone not), both using certificate credentials and the client credentials flow