FIELD NOTE / M365 / GRAPH / APPLICATION CONSENT
The integration needs one SharePoint site but can write to every site
The overnight integration copies approved drawings into one SharePoint library. Its token, however, carries an application permission capable of writing across the tenant. The job completes while tenant-wide authority remains uncontrolled. The repair is to reconstruct the operations it genuinely performs, grant resource-specific authority, and prove that every unrelated site returns access denied.
The situation: a prototype permission survives production
COMPOSITE SCENARIO: documented product behaviour combined with recurring operational failure patterns. No client-specific delivery claim is attached. Consider a Perth engineering supplier that receives approved drawing packages from an external project system. An unattended Azure-hosted job uses Microsoft Graph to create folders, upload revisions and update metadata in one SharePoint project site. During the prototype, the developer granted the application Sites.ReadWrite.All because narrower calls returned 403 errors.
The prototype becomes an operational dependency. Months later, a consent review finds that the service principal still holds tenant-wide SharePoint write authority. The client secret is stored in an automation setting, two departed contractors remain listed as application owners, and nobody can state which Graph endpoints the job invokes. Removing the permission immediately could stop project delivery; leaving it means one compromised workload identity can potentially alter content far beyond the intended site.
Microsoft Graph is enforcing the tenant-wide consent granted to the service principal. The written purpose covers one SharePoint site. The failure is that functional success became acceptance evidence while the application’s data boundary, credential lifecycle and negative-access behavior were never tested.
Contain without destroying the evidence
Name a business owner, application owner, SharePoint owner and security decision owner. Freeze new permission and credential changes except approved containment. Capture the application object ID, app/client ID, enterprise-application service-principal ID, tenant, publisher/verification state, owners, credentials and expiry dates, Graph app-role assignments, SharePoint resource grants, recent service-principal sign-ins, hosting boundary and deployment source.
Do not paste the secret into a ticket, rotate it before identifying every running instance, or delete the enterprise application merely to remove consent. Do not assume that removing an owner removes access: owners administer objects; tokens are authorised through the service principal’s grants and the resource permission model.
If there is evidence of compromise, follow the incident path: disable or block the workload identity as authorised, revoke credentials and consent, preserve sign-in/audit evidence, and assess affected sites. Contain the active incident before beginning the least-privilege migration.
Reconstruct the effective permission
Separate four objects that are often compressed into “the app”: the application registration defines the client and credentials; the service principal is the tenant-local workload identity; Graph application permissions are app-role assignments granted to that service principal; and SharePoint Selected permissions are explicit grants on sites, lists or items.
Decode a fresh access token from a controlled test run without logging the token itself. Record its tenant, audience, application identity and roles claims. Join those claims to the current Microsoft Graph permissions reference, then inspect resource-specific assignments. Review the code, network/API telemetry and sign-in logs to identify the endpoints actually used. A manifest describes requested access; a token and successful API call show effective access at that moment.
Also inventory non-Graph authority: Azure roles, Key Vault access, SharePoint legacy API permissions, pipeline identities, local configuration copies and any automation able to grant consent. Effective authority combines the workload identity, credential, API role, resource grant and running host.
Convert the job into an operation contract
List each business operation with resource, HTTP method, endpoint, required role and failure behavior. The drawing job may need to resolve a known site, enumerate one library, read existing metadata, upload a file, update selected fields and create a folder. It may not need tenant-wide site discovery, search across all SharePoint, site creation, permission management or deletion.
Test whether every required endpoint supports the proposed Selected permission. Sites.Selected scopes access at site-collection level; newer Selected scopes can target lists, list items, folders or files. Selected consent alone grants no resource access. The application also needs an explicit assignment on the target resource and a token containing the matching Selected scope.
Do not add Sites.Read.All merely to make tenant-wide discovery work unless discovery is an approved requirement. Store known site and drive identifiers or resolve a known hostname/path through supported calls. If a required endpoint cannot operate within the selected boundary, record the endpoint as an architecture constraint and keep global access out of the runtime design.
Separate runtime and grant-administration identities
The runtime identity should hold only the Selected application permission and the minimum target-resource role—read or write as demonstrated. A separate, tightly governed grantor performs the administrative assignment through the site/list permission endpoint. The runtime must not be able to expand its own SharePoint reach or grant application consent.
Choose an authentication method that fits the host. Prefer a managed identity or workload identity federation when the platform and deployment path support it. Otherwise use a controlled certificate or a short-lived, governed client secret with owner, vault, rotation, expiry and revocation evidence. Treat the application ID as a public identifier and the credential as secret material. Eliminate credentials embedded in source, scripts, documents and unmanaged settings.
Keep production and non-production identities separate. Scope their SharePoint grants to different sites. Name accountable owners by role and person, maintain a backup operator, and establish an expiry/review date for every grant even where expiry exists only in the review control.
Migrate permission without an untested outage
- Create or select the controlled runtime identity and credential path.
- Grant the required Selected scope in Entra ID.
- Use the separate grantor to assign the minimum role to the exact target site or narrower resource.
- Run the operation contract against synthetic production-shaped content.
- Execute negative calls against unrelated, similarly named and sensitive sites.
- Switch one bounded workload slice and observe business plus security evidence.
- Remove the tenant-wide app role from the old service principal.
- Reacquire a token and repeat positive and negative tests.
- Revoke obsolete credentials and retire the old identity only after rollback and reconciliation close.
Consent changes and tokens have timing effects. Do not accept a test performed with a token issued before the broad permission was removed. Record token issuance time and use a newly acquired token for the final boundary proof.
Prove allowed and denied paths
Positive tests cover every contracted operation on the target library: read, create, update, version, metadata and failure/retry behavior as applicable. Negative tests call an unrelated project site, a finance or people site, a similarly named site, another library in the target site if narrower scope is intended, and prohibited operations such as permission change or deletion.
Expected denial must be explicit, normally a 403/authorization failure for the prohibited resource. An empty result is ambiguous and fails the test. Confirm the runtime token contains the intended Selected role and contains no global SharePoint role. Enumerate the target resource permission object and match the service-principal identity and role. Review service-principal sign-ins and Graph activity evidence for the test interval.
Acceptance is one business outcome with bounded authority: the integration completes required work, cannot reach unrelated resources, cannot enlarge its own grant, uses a governed credential, and can be disabled or rotated by a second operator.
Operate application consent as a production control
Review workload identities at onboarding, release, credential rotation, ownership change and at least quarterly. Alert on new high-impact app-role assignments, ownerless applications, credentials approaching expiry, anomalous service-principal sign-ins and changes to resource grants. Keep the permission contract beside the deployment source and make its negative tests a release gate.
Selected permissions reduce the accessible resource set. Application code, host security, credential handling and data use still require separate tests. The app can still corrupt every item inside its granted boundary, exfiltrate data it may read, or leak through its host. Apply input validation, idempotency, audit, backup/recovery, host security and data minimisation.
PnP and Microsoft developer-community material is useful for implementation patterns and recurring 403 symptoms. Product behavior and permission identifiers must resolve to current Microsoft documentation and local token/API evidence. The durable result is an application whose effective authority matches a written and tested resource contract.