Graph sigue devolviendo 403 accessDenied

Victor Figueroa 0 Reputation points
2026-09-18T15:00:34.32+00:00

Tengo un problema persistente de 403 Forbidden (accessDenied) al acceder

a un sitio/drive de SharePoint Online vía Microsoft Graph, a pesar de que

el permiso de aplicación Sites.Selected está correctamente otorgado y

verificado por múltiples métodos. Ya agoté los pasos estándar de

diagnóstico y espero que alguien del equipo de Graph/SharePoint o de la

comunidad pueda orientarme sobre qué me estoy perdiendo.

  • Azure App Service usando una System-Assigned Managed Identity
  • Otorgado el permiso de aplicación "Sites.Selected" en Microsoft Graph
  • Otorgado el rol "write" sobre un sitio específico de SharePoint vía: POST /sites/{site-id}/permissions

Cualquier llamada a Graph usando un token de esta identidad contra el

sitio destino devuelve 403 Forbidden, incluyendo operaciones simples de

lectura:

  • GET /sites/{site-id}
  • GET /sites/{site-id}/drive
  • GET /sites/{site-id}/drives
  • GET /sites/{site-id}/permissions

Lo que ya verifiqué (con evidencia)

  1. Decodifiqué el token JWT de acceso — confirma que el rol está presente: { "roles": ["Sites.Selected"], "aud": "https://graph.microsoft.com" }
  2. Confirmé que el AppRoleAssignment existe a nivel de tenant vía: GET /servicePrincipals/{id}/appRoleAssignments — el appRoleId coincide con Sites.Selected en el catálogo de appRoles del Service Principal de Graph (isEnabled: true, allowedMemberTypes: Application).
  3. Confirmé que el permiso a nivel de sitio existe vía: GET /sites/{site-id}/permissions { "id": "i:0i.t|ms.sp.ext|{objectId}@{tenantId}", "roles": ["write"], "grantedToIdentities": [{"application": {"id": "{objectId}"}}] }
  4. Reproduje exactamente el mismo 403 usando un tipo de identidad completamente distinto — un App Registration estándar con Client Secret (flujo client credentials), con el mismo permiso Sites.Selected otorgado con admin consent, y el mismo permiso write a nivel de sitio. Mismo 403. Esto descarta que sea algo específico de Managed Identity.
  5. Reproducido en DOS sitios distintos: un Team Site conectado a un grupo de M365 (esperé más de 4 días para descartar demora de propagación) y un Communication Site nuevo (sin grupo M365). Ambos fallan de forma idéntica.
  6. Revisé "Acceso a API" en el SharePoint Admin Center — 0 solicitudes pendientes.
  7. Revisé las políticas de "Control de acceso" en el SharePoint Admin Center — políticas estándar (dispositivos no administrados, cierre de sesión inactiva, ubicación de red, autenticación legacy, restricción de OneDrive), nada que debiera afectar el acceso app-only / de Service Principals.
  8. Verifiqué la configuración a nivel de tenant: Get-SPOTenant | Select DisableCustomAppAuthentication → False (no está bloqueando autenticación de apps personalizadas)

¿Existe alguna configuración adicional a nivel de tenant, alguna función

en pureview, o algún requisito no documentado que pudiera estar

bloqueando el acceso app-only vía Sites.Selected, incluso cuando tanto

el permiso a nivel de aplicación como el permiso a nivel de sitio están

correctamente otorgados y verificados? Lo reproduje de forma consistente

en dos tipos de identidad distintos y dos tipos de sitio distintos, así

que no creo que sea una demora de propagación ni un error de

configuración en un solo recurso.

Gracias de antemano por cualquier or

Microsoft 365 and Office | SharePoint | Development
0 comments No comments

1 answer

Sort by: Most helpful
  1. Emily T 565 Reputation points Microsoft External Staff Moderator
    2026-09-18T17:15:29.97+00:00

    *Como la descripción de su problema está escrita principalmente en español, le responderé en español para su comodidad. Si prefiere recibir la información en otro idioma, no dude en indicármelo.

    *Esta respuesta se ha traducido automáticamente, por lo que puede contener errores gramaticales o expresiones poco naturales.

    Hola Victor,

    Gracias por la información detallada.

    Hay un punto que me gustaría verificar: el valor que aparece como {objectId} en tu ejemplo. ¿Era simplemente un marcador de posición o el permiso del sitio se concedió realmente utilizando el Object"id"? Para Sites.Selected, el valor de application.id en la concesión de permisos del sitio debe ser el Application ID. Si se utilizó el Object "id" en su lugar, es posible que el permiso no esté asociado con la aplicación prevista.

    Además, separaría la prueba GET /sites/{site-id}/permissions de las demás. Ese endpoint requiere Sites.FullControl.All, por lo que sería esperable recibir un error 403 si solo se utiliza Sites.Selected. El problema más importante es que GET /sites/{site-id} y los endpoints relacionados con la unidad (drive) también están devolviendo errores 403.

    Si se confirma que el Application (Client) "id" es correcto, recomendaría comprobar si el sitio está sujeto a un Authentication Context, una sensitivity label o una política de Conditional Access que pueda bloquear el acceso app-only.

    ¿Podrías confirmar si el permiso del sitio se concedió utilizando el Application (Client) "id" y compartir la respuesta de error completa, incluidos el request-id y el correlation-id, de una solicitud GET /sites/{site-id} que esté fallando?
    Puedes consultar los detalles en este documento:
    Directiva de acceso condicional - SharePoint in Microsoft 365 | Microsoft Learn
    Descripción del consentimiento específico de recursos para Microsoft Graph y SharePoint Online | Mi…

     

    Was this answer helpful?


Your answer

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