Sliick Files + SharePoint: storage setup
Point Sliick Files at SharePoint Online and every file your Salesforce org writes
through the Sliick Files API lands
in a SharePoint document library instead of Salesforce Files. Your callers don’t
change. The same uploadFiles, listFiles, and getDownloadUrls operations
run, and the bytes flow to SharePoint through Microsoft Graph. You keep your
files where compliance wants them, off the Salesforce storage bill, and visible
to the rest of your Microsoft 365 estate.
The connection runs through a Named Credential that Sliick sets up in your org when you connect. Which credential gets created depends on the authentication mode you choose:
SharePoint_Graph_App(External CredentialSharePoint_Graph_App) for Service Principal mode.SharePoint_Graph_User(External CredentialSharePoint_Graph_User) for Per-User Delegated mode. Delegated mode also creates aSharePoint_MicrosoftAuth Provider.
Connect creates the credential; the admin then completes the OAuth wiring once per org, entering the Entra app credentials and granting the principal. After that, end users only pick a Site URL in the Sliick Files setup app - there are no Client ID, Secret, or Tenant inputs anywhere in Sliick records. Every Microsoft OAuth credential lives in Salesforce Setup, not on a Sliick object.
The one real decision is which authentication mode to run:
- Service Principal (app-only). Apex calls Graph as the app itself, with no user context. This is the path most orgs use: it works for back-end jobs, batch document generation, and any code path where no human is signed in. The trade-off is that SharePoint audit trails attribute every action to the app principal, not to the person who triggered it.
- Delegated (per-user). Each Salesforce user signs in to Microsoft once, and
Apex calls Graph on their behalf. SharePoint audit trails show the human user.
Access is the intersection of the same per-site
Sites.Selectedgrant used by app-only mode and what that user can already see in SharePoint, so it’s the narrowest of the two. The trade-off is that every user has to complete a one-time sign-in, and back-end paths with no signed-in user won’t work.
If you’re unsure, start with Service Principal. It’s the tested path, it covers back-end automation, and you can add Delegated mode later without undoing anything. The two modes don’t conflict, and you can configure both if you need to support a mix.
A note before you start on Delegated mode specifically: Service Principal has been smoke-tested end to end. The Delegated steps are derived from Salesforce and Microsoft Entra documentation plus the per-user OAuth flow baked into the packaged External Credential. They haven’t yet been exercised against a real tenant. Treat the Delegated section as a solid starting point and expect to iterate the first time you run it against a live SharePoint tenant. The caveat is repeated inline where it matters.
1. Microsoft Entra app registration
This whole section happens in the Azure Portal (Microsoft’s admin console) and requires tenant admin rights (Global Administrator or Application Administrator) on the Microsoft 365 tenant that owns your SharePoint sites. If you aren’t a tenant admin, hand this section to whoever is - most steps below require their account.
Vocabulary, so the screens make sense
- Tenant - your organisation’s Microsoft 365 account. The tenant owns Entra ID (formerly Azure AD), SharePoint Online, Exchange, and so on. Its identity is a GUID, the “Tenant ID”.
- Entra ID - Microsoft’s identity service. Formerly “Azure AD”.
- App registration - the Entra ID record that represents a third-party application (Sliick Files, here). It holds the Client ID, secrets, and permission grants.
- Service Principal / Application permission - the app calls Graph as itself, no user context. Best for back-end integrations.
- Delegated permission - the app calls Graph on behalf of a signed-in user. Best when you want SharePoint audit trails to show the human, not the app.
- Admin consent - the moment a tenant admin clicks “Grant admin consent” and the permission becomes usable. Without consent, every Graph call returns 403.
1a. Open Microsoft Entra ID
- Sign in to https://portal.azure.com as a tenant admin.
- In the search bar at the top, type Microsoft Entra ID and open the service.
- On the Overview tab, copy the Tenant ID (a GUID under “Basic information”). Write it down - you’ll need it for Salesforce.
1b. Create the app registration
- In Entra ID, click App registrations in the left sidebar, then + New registration at the top.
- Name -
Sliick Files (SharePoint Graph)(or any label your tenant uses). Users see this name on the consent screen. - Supported account types - Accounts in this organizational directory only (Single tenant).
- Redirect URI - leave blank for now. You’ll add it later (step 3b) if you use Delegated mode; Service Principal mode doesn’t need one.
- Click Register.
- On the new app’s Overview page, copy:
- Application (client) ID - write down as Client ID.
- Directory (tenant) ID - confirm it matches what you wrote in step 1a.
1c. Create a client secret
The “client secret” is the password Entra accepts when Salesforce proves it’s the Sliick app.
- In your app registration, click Certificates & secrets in the left sidebar.
- On the Client secrets tab, click + New client secret.
- Description -
Sliick Files Salesforce. - Expires - pick a duration. Microsoft caps secret lifetime at 24 months. Pick the longest available (24 months) and set a calendar reminder to rotate before expiry. When the secret expires, Sliick stops working until a new one is issued and re-entered in step 2.
- Click Add.
- The new secret appears in the table. Copy the Value column immediately.
The secret value is shown exactly once. If you navigate away before copying it, you must delete this secret and create a new one. Paste it into a password manager, or keep the tab open until you’ve finished step 2 below.
1d. Grant Microsoft Graph permissions
The permissions you add depend on which mode you’ll run.
-
In your app registration, click API permissions in the left sidebar.
-
Click + Add a permission.
-
Pick Microsoft Graph (the big tile).
-
Choose the permission type:
- For Service Principal mode, click Application permissions. Search for
Sites.Selectedand check the box. Click Add permissions. - For Delegated mode, click Delegated permissions. Search for and
check
Sites.Selectedandoffline_access. Click Add permissions.
Both modes use
Sites.Selected- the only difference is the permission type (Application vs Delegated). You can add both if you intend to support both modes; they don’t conflict. - For Service Principal mode, click Application permissions. Search for
-
Back on the API permissions page, you’ll see the new permissions with a yellow “Not granted” status. Click Grant admin consent for [tenant name] at the top, then Yes to confirm. The status column flips to green Granted for [tenant].
Why
Sites.Selectedfor both modes? It’s Microsoft’s recommended least-privilege pattern, and the whole point of this setup: the app has no access to anything by default - you explicitly grant it the single site Sliick will manage (step 1e). Tenant admins can audit exactly which site Sliick can reach. The broad alternatives (Sites.ReadWrite.Allapplication, orSites.Read.All+Files.ReadWrite.Alldelegated) would let the app reach every SharePoint site - in delegated mode, every site the signed-in user can reach - which most enterprise security reviews reject. In Delegated mode theSites.Selectedgrant is also intersected with the signed-in user’s own permissions, so access is the narrowest of the two.
1e. Grant the app access to the SharePoint site (both modes)
Sites.Selected is least-privilege: the app can only access sites that have been
explicitly granted to it. Make a one-time write grant, via Microsoft Graph, for
the single site Sliick will manage. This applies to both Service Principal
and Delegated modes - it is the app (service-principal) grant that scopes Sliick to
one site; in Delegated mode the signed-in user must additionally have their own
access to that site.
There’s no Azure Portal UI for this - you call Graph directly. The easiest tool is Graph Explorer, Microsoft’s web-based Graph client.
- Open https://developer.microsoft.com/graph/graph-explorer and sign in as a tenant admin (top-right).
- The first time you run a Graph call as admin, Graph Explorer prompts for additional consent. Approve it.
Step 1 - Find the site ID for the SharePoint site you want Sliick to manage:
-
Look at the SharePoint site URL in your browser. It looks like
https://contoso.sharepoint.com/sites/marketing. Note the hostname (contoso.sharepoint.com) and the site path (/sites/marketing). -
In Graph Explorer, set the method to GET and the URL to:
https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/marketing -
Click Run query. The response includes an
idfield that looks likecontoso.sharepoint.com,8f3...guid...,2a1...guid.... Copy the entireidvalue - that’s the composite site ID.
Step 2 - Grant the Sliick app write access to that site:
-
In Graph Explorer, set the method to POST and the URL to (paste the site
idfrom step 1, replacing{site-id}):https://graph.microsoft.com/v1.0/sites/{site-id}/permissions -
Set Request body to (replace
<your-app-client-id>with the Client ID from step 1b):{ "roles": ["write"], "grantedToIdentities": [ { "application": { "id": "<your-app-client-id>", "displayName": "Sliick Files (SharePoint Graph)" } } ] } -
Click Run query. A
201 Createdresponse confirms the grant.
Available roles: read, write, owner. Sliick needs at least write to
upload, replace, and delete files.
Grant only the one site Sliick will manage. Sliick connects to a single site (the Site URL you enter in the setup app resolves to one site), so granting the app additional sites widens its reach with no benefit. Keep the grant to the single site you configure.
Final values you’ll need for Salesforce
- Tenant ID (step 1a)
- Client ID = Application (client) ID (step 1b)
- Client Secret (step 1c)
2. Salesforce setup - Service Principal mode
This is the path most orgs use. The app authenticates to Microsoft on its own; no individual Salesforce user has to sign in.
How to get to Setup: in Salesforce, click the gear icon in the top-right and choose Setup. The setup tree appears on the left; use the Quick Find box at the top of the left sidebar to jump to any page named below.
Before either mode: assign the Sliick Files permission sets. In Setup → Permission Sets, then Manage Assignments → Add Assignment, assign Sliick Files Admin to admins who configure storage and open Sliick Settings, and Sliick Files User to anyone who uploads, views, tags, or shares files. These are the base grants that let a user use Sliick Files at all; the SharePoint credential grant below is in addition to them. This applies to both Service Principal and Delegated mode.
-
In Setup, Quick Find for Named Credentials. On the External Credentials tab, click into SharePoint Graph (App). Find the Authentication Parameters section.
-
Click the dropdown next to the AuthProviderUrl row, then Edit. Change its value from the deployed default
https://login.microsoftonline.com/common/oauth2/v2.0/tokento your tenant-scoped form (paste your Tenant ID from step 1a):https://login.microsoftonline.com/<your-tenant-id>/oauth2/v2.0/tokenThe default
/common/endpoint works for multi-tenant apps; Sliick is single-tenant, so pin it to your tenant explicitly. -
On the same page, scroll to the Principals section. Click the dropdown next to the App_Only row, then Edit / Configure. Set:
- Username = Microsoft app Client ID (from step 1b)
- Password = Microsoft app Client Secret (from step 1c)
The Username/Password labels are misleading - these aren’t a person’s credentials. They’re the OAuth client_id/client_secret pair that Salesforce sends to Microsoft when requesting an access token.
-
Save.
-
Grant the running user the
sliick__SharePoint_Graph_App-App_Onlyexternal credential principal access. Because the credential is created at connect time, no packaged permission set can reference it. Add the grant on a permission set you control and assign that permset to anyone who will use Sliick Files (including admins). To do this:- Setup → Quick Find for Permission Sets → open (or create) a permission set you manage for storage users.
- Under External Credential Principal Access, add the
SharePoint Graph (App)principal (sliick__SharePoint_Graph_App-App_Only). - Click Manage Assignments → Add Assignment → check users → Next → Assign.
The Auth Provider SharePoint_Microsoft is not used by Service Principal
mode. You can ignore its PLACEHOLDER_FILLED_BY_storageSetup values if you’re
only running this mode.
Verify
In Sliick Settings, pick SharePoint, set Authentication Mode to Service Principal, paste a SharePoint Site URL you granted in step 1e, and click Discover Site and Libraries. The site and its document libraries list within a few seconds. If discovery fails, the error text tells you which step is misconfigured (a Microsoft 401/403 versus a Salesforce “isn’t fully configured”).
3. Salesforce setup - Delegated (Per-User) mode
Status: untested. Service Principal mode has been smoke-tested end to end against
uqtest.sharepoint.com/teams/ACESaleforcesFileTest. Delegated mode hasn’t yet been exercised against a real tenant. The steps below are derived from Salesforce and Microsoft Entra documentation plus the per-user OAuth flow baked into theSharePoint_Graph_UserExternal Credential. Treat them as a starting point and expect to iterate the first time the path runs against a real SharePoint tenant.In particular, verify the
Sites.Selecteddelegated scope first. Delegated mode now requests onlySites.Selected+offline_access(no tenant-wideSites.Read.All/Files.ReadWrite.All), relying on the per-sitewritegrant from step 1e for access - the same way Service Principal mode reaches files. App-only provesSites.Selectedalone covers drive read/write, but the delegated variant (its token intersected with the user’s own permissions) should be confirmed end to end against a live tenant - upload, download, and delete - before you rely on it.
Delegated mode is right when you need uploads attributed to the signed-in
Salesforce user instead of an anonymous app principal. Both modes now use per-app,
per-site Sites.Selected grants, so the choice is purely about attribution, not
breadth of access.
3a. Auth Provider
- Setup → Auth. Providers → SharePoint (Microsoft Graph) → Edit.
- Set:
- Consumer Key = Microsoft app Client ID
- Consumer Secret = Microsoft app Client Secret
- Authorize Endpoint URL =
https://login.microsoftonline.com/<your-tenant-id>/oauth2/v2.0/authorize - Token Endpoint URL =
https://login.microsoftonline.com/<your-tenant-id>/oauth2/v2.0/token
- Save.
- The Auth Provider detail page now shows a Callback URL, for example
https://<orgDomain>/services/authcallback/SharePoint_Microsoft. Copy it.
3b. Register the callback in Microsoft
- Azure Portal → your app registration → Authentication → Add a platform → Web → paste the Callback URL from step 4 as a Redirect URI → save.
3c. Per-user sign-in (each Salesforce user, once)
Each Salesforce user who needs SharePoint access does this once:
- From the user’s avatar menu → Settings → My Personal Information → Advanced User Details.
- Scroll to Authentication Settings for External Systems → New.
- Choose:
- External System Definition Type = External Credential
- External System Definition = SharePoint_Graph_User
- Per-User Principal = (the Per_User principal)
- Save - Salesforce redirects to Microsoft sign-in. Complete the OAuth prompt and grant the listed permissions.
- After the redirect back to Salesforce, the row shows status Configured / Authenticated.
The Sliick Files setup app has an Open Microsoft Sign-In (Personal Settings) button that opens the Personal Settings page directly to shortcut steps 6-8.
Verify
Switch the Sliick Settings auth mode to User Sign-In. Click Open Microsoft
Sign-In, complete sign-in for your own user (if you haven’t already), then click
Discover Site and Libraries. With Sites.Selected, access is the intersection
of the app’s per-site grant (step 1e) and your own SharePoint access - so enter
the single granted Site URL, and it resolves only if you can also reach it in
SharePoint. An ungranted site, or one you personally can’t reach, returns
access-denied.
Troubleshooting
| Symptom (where it appears) | What it means |
|---|---|
LWC: Site URL is required | You clicked Discover without a Site URL. |
LWC / Apex: The external credential isn't fully configured | The EC’s AuthProviderUrl wasn’t updated to the tenant-scoped token endpoint, or the App_Only principal has no Username/Password. Re-walk Section 2 steps 2-3. |
Microsoft: AADSTS90002: Tenant '<guid>' not found | The tenant ID in the AuthProviderUrl (Service Principal) or Authorize/Token URLs (Delegated) is wrong. Double-check Azure Portal → Microsoft Entra ID → Overview. |
Microsoft: AADSTS7000215: Invalid client secret provided | Wrong client secret on the App_Only principal (Service Principal) or the Auth Provider (Delegated). Copy a fresh secret from Microsoft and re-enter it. |
Microsoft Graph: 403 accessDenied on /sites/root | Expected when using Sites.Selected. Root isn’t granted. Use a Site URL you’ve explicitly granted (Section 1e) instead. |
Microsoft Graph: 403 accessDenied on a granted site | The site grant in Section 1e didn’t land for this app. Re-confirm grantedToIdentities[].application.id matches your Client ID exactly. |
LWC: We couldn't access the credential(s) | The running user lacks the External Credential Principal access. Grant the SharePoint Graph principal on a permission set you control and assign it. |
When you switch back to the LWC
The Sliick Settings LWC only collects two things:
- Authentication Mode (Service Principal or User Sign-In)
- Site URL
Once the manual setup above is done, once per org, every admin or end user only needs to paste a Site URL and click Discover. Each subsequent SharePoint site they want to use needs:
- Service Principal: a per-site grant (Section 1e) in Microsoft Graph.
- Delegated: nothing extra - the user already has access to whatever SharePoint sites they can normally see.
With storage pointed at SharePoint, the rest of Sliick Files works exactly as documented. Every call through the Sliick Files API - Apex, Flow, or the upload component - routes bytes to SharePoint without a single line of provider-specific code.
We'll audit your architecture, security, and integration posture.