Introduction
If you're setting up app-only permissions to access the SharePoint Online REST API and run into persistent “403 Forbidden”, “Unauthorized”, or “Unsupported app only token” errors, you're not alone. One of the most common misconfigurations we see is the use of a client secret instead of a self-signed X.509 certificate when authenticating with Azure AD. While client secrets work for many Azure AD apps, SharePoint has stricter requirements for app-only access. Examples of SharePoint endpoints:
- PnP PowerShell - PnP PowerShell Overview
- SharePoint REST API - Determine SharePoint REST service endpoint URIs
- SharePoint CSOM - Get a quick overview of the SharePoint object model
What’s Going Wrong?
When customers configure app-only access using Azure AD, they often assume that a client secret is sufficient because they will be able to obtain a valid token. However, SharePoint Online requires certificate-based authentication for app-only access. If you attempt to use a client secret, SharePoint will reject the request with an access error—even if the app has the correct permissions.
Example:
Why SharePoint Requires a Certificate?
SharePoint Online uses a different trust model for app-only access. It expects the app to authenticate using a certificate, which provides a higher level of security and ensures that the app identity is strongly validated. This is especially important for scenarios where the app is accessing resources without a user context.
How to Fix It
To resolve this issue, you’ll need to:
- Generate a self-signed X.509 certificate.
- Update the app in Azure AD to include the certificate (PnP-PowerShell/Samples/SharePoint.ConnectUsingAppPermissions at master · pnp/PnP-PowerShell · GitHub)
- Use the certificate to authenticate and obtain an access token.
Example:
Connect-PnPOnline -Url "https://contoso.sharepoint.com" -ClientId 6c5c98c7-e05a-4a0f-bcfa-0cfc65aa1f28 -CertificatePath 'c:\mycertificate.pfx' -CertificatePassword $password -Tenant 'contoso.onmicrosoft.com'