How To
Summary
Out-of-support Authentication Patterns in SharePoint Online as of April 2026
Objective
High‑level diagnosis:
Action being performed is app‑only access to SharePoint Online using:
- CSOM 15.x (SharePoint 2013 era)
- ACS app-only tokens
- WCF + HttpWebRequest
- .NET Framework 4.6.2
- No Azure AD App Registration
- No SharePoint Add‑in model trust
This is now blocked, even with “Legacy Auth Enabled” which results in the 401 error.
Result:
SharePoint Online rejects the request during EnsureFormDigest() à 401 / 403
Environment
SharePoint online
Steps
Error #1: 401 Unauthorized at EnsureFormDigest()
Microsoft.SharePoint.Client.ClientContext.GetFormDigestInfoPrivate()
This is almost certainly because Azure ACS (Access Control Service) app-only authentication was fully retired on April 2, 2026.
All ACS-based tokens (the old client ID and secret from your site) fails validation with 401s, even if the JWT decoded correctly in testing or previously worked.
This means:
- Request reached SharePoint
- SharePoint attempts to validate the security context
- SharePoint does not recognize the token as a valid app principal
- No valid User or App-only principal is associated
*This is not a networking issue. This is an authentication pipeline rejection
Error #2: Forbidden + X-MSDAVEXT_Error=917656
Access denied.
This is the classic WebDAV / legacy auth rejection.
It fires when code uses File.SaveBinaryDirect (or direct PUT to /_vti_bin/ endpoints) because those paths rely on cookie-based forms auth or legacy credentials. They do not carry or honor an OAuth Bearer token.
Even if your initial ClientContext has a valid modern token, SaveBinaryDirect bypasses the CSOM request executor and falls back to legacy behavior, which is now blocked in most tenants.
If CSOM is version (15.0.4849.1000 for example) and (.NET 4.6.2), they were never designed for current SPO auth enforcement. They still “work” for the REST paths but are fragile.
TIP: Before opening files in this location, you must first browse to the web site and select the option to login automatically.
Key headers in your error detail:
Header | Meaning |
|---|---|
X-Forms_Based_Auth_Required | SharePoint expects an interactive or modern auth flow |
Cannot contact web site or does not support SharePoint Online credentials | CSOM client/auth flow is not supported |
X-MS-InvokeApp | SharePoint attempted, then failed, modern auth |
In summary, this is SharePoint Online explicitly rejecting legacy client behavior
Why “Legacy Auth Enabled” does NOT work with it being Enabled
Legacy auth (basic/NTLM/forms) is a separate tenant setting (Set-SPOTenant -LegacyAuthProtocolsEnabled $true/false). ACS retirement is the hard stop, independent of that flag.
To clarify, Legacy Auth Enabled does NOT mean:
- ACS app-only tokens will work
- SharePoint Add‑in auth is allowed
- CSOM 15.x can do app-only uploads
Translation:
- Old username/password flows might still work
- Some basic SOAP/WCF calls might pass
NOTE: ACS-based app-only auth is effectively deprecated, even if not loudly documented.
Why JWT “can look correct” but still fails
Azure ACS (Access Control Service) app-only authentication was fully retired on April 2, 2026. All ACS-based tokens (the old client ID and secret from appregnew.aspx/appinv.aspx) now fail validation with 401s, even if the JWT decoded correctly in testing or previously worked.
Example: “Token when decoded shows correct aud = https://tenant.sharepoint.com” (Example only)
That’s necessary but not sufficient per MS.
Missing or invalid pieces usually include:
- No valid App Principal registered in SharePoint Online
- Token issued by ACS, not Azure AD
- No roles / scp claims recognized by SPO
- Token not trusted for CSOM form digest operations
- Token audience mismatch at resource-level, not tenant-level
Explanation: SharePoint now expects Azure AD issued tokens, not ACS.
Resolve Options
Option 1: Azure AD App Registration and current CSOM ver
ACS is gone!! You must finish the Azure AD app registration you mentioned having trouble with. It is the supported path and works perfectly with CSOM for true resolve.
Quick setup (Tested pattern for WCF/.NET Framework services):
- In Entra ID à App registrations à New registration:
- Name: e.g. “WCF-SPO-AppOnly”
- Supported account types: Accounts in this organizational directory only
- Redirect URI: leave blank (daemon/app-only)
- API permissions à Add a permission à Microsoft SharePointàApplication permissions àSites.FullControl.All (or Sites.ReadWrite.All and Sites.Manage.All if you want least privilege). Grant admin consent.
- Certificates & secrets à add a client secret (or better: upload a certificate).
- Record: Client ID, Tenant ID, Secret (or cert thumbprint).
Token acquisition in code (MSAL: Does work on .NET 4.6.2):
C#
using Microsoft.Identity.Client;
using System.Threading.Tasks;
// In your WCF service (or helper class)
private async Task<string> GetSPOAccessTokenAsync(string clientId, string clientSecret, string tenantId, string tenantName)
{
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login to MS Online /{tenantId}"))
.Build();
var result = await app.AcquireTokenForClient(new[] { $"https://{tenantName}.sharepoint.com/.default" })
.ExecuteAsync();
return result.AccessToken; // This JWT aud will be exactly https://tenant.sharepoint.com (the one you already confirmed is correct)
}
Certificate is strongly recommended (avoids secret expiration and some “Unsupported app-only token” edge cases that appear in 2025–2026 tenants).
Generate a self-signed cert, upload the .cer to the app registration, and use .WithCertificate(new X509Certificate2(...)) instead of secret.
*This has worked for many customers based on searches supporting this issue..
Step 2: Attach the Bearer token to your ClientContext (works even with old CSOM 15)
C#
ClientContext ctx = new ClientContext(siteUrl);
string accessToken = await GetSPOAccessTokenAsync(...);
ctx.ExecutingWebRequest += (sender, args) =>
{
args.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + accessToken;
// Optional: force modern headers
args.WebRequestExecutor.RequestHeaders["X-RequestDigest"] = ""; // will be populated automatically
};
ctx.ExecuteQuery(); // This should now succeed for GetFormDigest
NOTE: You do NOT need Graph if you don’t want it.
- Works with file uploads
- App‑only
- Supported
- No user interaction
- No ACS
What changes:
- Create Azure AD App Registration
- Grant SharePoint Application permissions
- Use PnP.Framework or updated CSOM
- Obtain token from Azure AD (https://{tenant}.sharepoint.com/.default)
Option 2: Azure AD App and Microsoft Graph combined
- Fully supported
- Best diagnostics
- Strong permissions model
But:
- Requires Graph endpoints
- Slight API differences
Option 3: Fix the upload method
Replace any File.SaveBinaryDirect calls with the modern CSOM path:
C#
using (var fs = new FileStream(fileFullPath, FileMode.Open))
{
var folder = ctx.Web.GetFolderByServerRelativeUrl(folderServerRelativeUrl);
ctx.Load(folder);
ctx.ExecuteQuery(); // or batch it
var fileInfo = new FileCreationInformation
{
ContentStream = fs,
Url = Path.GetFileName(fileFullPath),
Overwrite = true
};
Microsoft.SharePoint.Client.File file = folder.Files.Add(fileInfo);
ctx.Load(file);
ctx.ExecuteQuery(); // This uses REST/client.svc à fully supports Bearer token
}
For >2 GB files you would switch to upload sessions (newer CSOM).
Option 4: Upgrade CSOM
- Uninstall the old 15.0.4849 NuGet/reference.
- Install latest Microsoft.SharePointOnline.CSOM (16.1.x) via NuGet.
- It still targets .NET Framework 4.6.2+ and adds better token helpers + chunked upload support.
- (Optional but cleaner) Switch to PnP.Framework for AuthenticationManager.GetAzureADAppOnlyAuthenticatedContext(...), zero manual header code.
Option 5: SharePoint Add‑in Model (Only if Tenant still allows it)
This works only if:
- Tenant explicitly allows SharePoint Add‑ins
- App is registered at: tenant-admin.sharepoint.com/_layouts/15/appregnew.aspx
- Permissions set via appinv.aspx
NOTE: Many tenants now block this entirely
Microsoft does not recommend starting new solutions with this.
What will never work!!
- ACS tokens (acs.windows.net)
- CSOM 15.0.x
- HttpWebRequest with bearer injection
- WCF proxying CSOM
- App‑only without Azure AD registration
- Relying on “Legacy Auth Enabled”
Minimum technical changes to fix your code
If you want the smallest delta from where you are now:
- Upgrade CSOM if not current
- Use PnP.Framework or latest CSOM NuGet
- Create Azure AD App Registration
- Application permissions:
- Sites.FullControl.All (or scoped via Sites.Selected)
- Application permissions:
- Switch token acquisition
- Use Microsoft.Identity.Client (MSAL)
- Resource: //{tenant}.sharepoint.com/.default
- Continue using ClientContext if configured
- You can still upload files exactly like today
Quick validation checks
- Run Get-SPOTenant | Select DisableCustomAppAuthentication, LegacyAuthProtocolsEnabled DisableCustomAppAuthentication should be $false (Rarely the issue now).
- Confirm your Entra app has the SharePoint application permission granted admin consent.
- Test the token acquisition standalone (decode JWT: aud must be https://<tenant>.sharepoint.com and scp or roles should include the Sites.* permission).
- .NET TLS: Add ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13; at app start (old .NET defaults can still cause issues).
After all the changes mentioned, both the 401 and the WebDAV/Forbidden errors should disappear.
IMPORTANT: The migration from ACS is non-negotiable. Microsoft has no extensions.
TIP: If you hit “Unsupported app-only token” after switching to Entra, switch the app to certificate auth which is a common fix in many tenants.
Additional Information
To summarize why your current setup was impacted:
Microsoft changes that can affected you:
- Progressive ACS retirement
- Expanded conditional access enforcement
- CSOM legacy auth tightened
- SharePoint Online rejecting non-AAD app principals
This is why your code:
- Compiles
- Gets a token
- Fails at runtime with 401/403
High-level summary:
- This reported issues sample would not be considered as a bug in your code.
- This is a platform deprecation issue.
NOTE: The moment you use Azure AD issued app-only tokens, the 401 errors should disappear.
Document Location
Worldwide
Was this topic helpful?
Document Information
Modified date:
28 April 2026
UID
ibm17271115