Tag Archives: Microsoft 365 Governance

KBA, how-to, thoughts related to Microsoft 365 SharePoint Governance

Proactive SharePoint: Essential Initial Configurations for Every New Microsoft 365 Tenant

In this article I will share what I would recommend to configure on every new Microsoft 365 Tenant.

The Challenge: Why Many Microsoft 365 Tenants Become Unmanageable and Inefficient Over Time

Many organizations adopting Microsoft 365 quickly discover that while the platform offers immense power, its default configuration often leaves crucial features disabled. These “dormant” functionalities, designed to enhance data governance, search capabilities, content management, and user experience, remain untapped. The real problem arises when a tenant matures: as users populate SharePoint sites and OneDrive accounts with vast amounts of information, and as collaboration intensifies, attempts to enable these critical features become incredibly complex, disruptive, and even risky. Retrofitting governance, re-indexing content, or restructuring information architecture on an existing, data-rich tenant can lead to compliance headaches, data inconsistencies, user frustration, and significant administrative overhead. SharePoint administrators frequently struggle with the technical debt accrued from these missed initial configurations, spending countless hours trying to bring order to an environment that could have been optimally set up from day one.

Consider the following.

Ownerless resources

Having an owner for every Microsoft 365 resource should be enforced from day one.

Sensitivity labels

This step is an essential prerequisite for the other governance features. I have an article explaining ownerless Microsoft 365 groups policy in details and more KBAs regarding ownerless SharePoint resources.

Oversharing in SharePoint

Oversharing in SharePoint is a serious problem. The earlier you start addressing it – the easier you life as SharePoint engineer. Here are some thought: Control Oversharing in SharePoint Online: Smarter Access Management in Microsoft 365

User profiles to Term Store mapping

There is an OotB misconfiguration in Microsoft 365 User Profiles mapping to Term Store Metadata. Here is the KBA how to configure User Profiles correctly.


WIP


Why this approach?

  • Relatability: It immediately speaks to the pain points experienced by many SharePoint admins (“unmanageable,” “inefficient,” “struggling with it,” “technical debt”).
  • Highlights the “Why”: It explains why these features are off and why it’s a problem to turn them on later.
  • Emphasizes Proactivity: It sets the stage for your solution, which is about proactive setup.
  • Strong Call to Action (Implied): It makes the reader understand that your KBA will provide the solution to avoid these common pitfalls.

Controlling Oversharing in SharePoint Online: Smarter Access Management in Microsoft 365

Oversharing remains one of the most persistent challenges in SharePoint Online. With the introduction of Microsoft Copilot and its AI-powered search capabilities, the issue has become even more visible—and more urgent to address. Microsoft has acknowledged this by introducing the SharePoint Advanced Management suite, aimed at helping administrators to bolster content governance throughout the Microsoft Copilot deployment journey.

Why Does Oversharing Happen?

In most cases, oversharing is unintentional. Based on my experience, the root causes typically fall into four categories:

  1. Unaware Sharing: A user shares a site, library, or folder without realizing it contains sensitive information.
  2. Unaware Uploading: A user uploads sensitive content to a location that is already broadly shared.
  3. Human Error: Mistakes like selecting the wrong group or sharing a folder instead of a file.
  4. Convenience: Users opting to share with “Everyone” to avoid the hassle of managing individual permissions.

Why It’s a Bigger Problem Today

In the past, search in Microsoft 365 was content-driven—you had to know what you were looking for. Today, search is context-driven. Microsoft 365 proactively surfaces content with suggestions like “Here’s what might be interesting to you” or “Here’s what others are working on.” This increases the risk of oversharing content being exposed.

Separate issue, non-technical, but related to the subject – not every user knows that search in Microsoft 365 is security-trimmed, i.e. provides results from only what this specific user has access to. Sometimes people might think of Microsoft 365 search the same way as general internet search (If a can see it – then everyone can see it, or why my private documents appear under Bing search?).

The Admin Dilemma

As SharePoint administrators, we’re caught in a classic catch-22:

  • Complex Microsoft products
  • Users prone to mistakes
  • Management demanding simple, fast solutions

What seemed like straightforward fixes for oversharing actually concealed the true issue, generating new problems, increasing admin burden, perplexing users, and ultimately hurting company productivity. Examples are (I would never do that):

  • Exclude sites from search indexing (Set “Allow this site to appear in search results?” to No)
  • Turn off Item insights, turn off People insights (turn off Delve)
  • Truncate enterprise search with “official” sites only (via query)

Microsoft offers two solutions: “Restrict discovery of SharePoint sites and content” and “Restricted SharePoint search”. Both solutions aimed to exclude content from search and from Copilot. Microsoft: “Restricted SharePoint Search allows you to restrict both organization-wide search and Copilot experiences to a curated set of SharePoint sites of your choice… and content users own or that they have previously accessed in Copilot.”. “With Restricted Content Discovery, organizations can limit the ability of end users to search for files from specific SharePoint sites.”

Microsoft clearly says that “limit the ability of end users to search” is a temporary measure that “gives you time to review and audit site permissions”… “to help you maintain momentum with your Copilot deployment while you’re implementing comprehensive data security”. Also: “Sites identified with the highest risk of oversharing can use Restricted Content Discovery to protect content while taking time to ensure that permissions are accurate and well-managed”.

Microsoft highlights that “Overuse of Restricted Content Discovery can negatively affect performance across search, SharePoint, and Copilot. Removing sites or files from tenant-wide discovery means that there’s less content for search and Copilot to ground on, leading to inaccurate or incomplete results”.

And finally “Restricted Content Discovery doesn’t affect existing permissions on sites. Users with access can still open files on sites with Restricted Content Discovery toggled on.”. I.e. solutions “Restricted SharePoint Search” and “Restricted Content Discovery” do not solve the root cause of the problem (oversharing), but make the problem less visible.

With over 15 years of experience in SharePoint and more than a decade working with Microsoft 365 and Azure—including large-scale tenants—I’ve seen this problem evolve. Now, with Copilot in the mix, it’s more critical than ever to implement a robust access management strategy.

Controlling Oversharing in SharePoint Online: Smarter Access Management in Microsoft 365

How to solve the real oversharing problem
(My Ideal “No-Oversharing” Tenant Configuration)

Here’s what I would recommend for minimizing oversharing in a Microsoft 365 environment (think of it as SharePoint Governance):

1. Remove “Everyone” and “Everyone Except External Users”

Disable these groups in the people picker to prevent broad, indiscriminate sharing. Instead, provide other options for sharing content with larger audiences (see below).

2. Implement Sensitivity Labels for Sites

  • Enforce mandatory sensitivity labels for all sites.
  • Labels should control site visibility (e.g., Private, Public) and be clearly named

The label is visible across all interfaces—Teams, SharePoint, libraries, lists, folders—so users always know how wide the content is shared from the sensitivity label.

3. Empower Users with Guardrails

  • Allow users to create Teams and communities, but enforce sensitivity labels.
  • Enable requests for standalone sites (Team or Communication) with required labels.
  • Disallow private or shared channels under public Teams to avoid label mismatches (e.g., a private channel labeled “Public”).

Benefits of This Approach

Once implemented:

  • Users will always know whether a site is private or public.
  • Sharing with “Everyone” on private sites will be technically impossible.
  • Users needing broad access can request public sites, e.g.
    • Public Teams for collaboration with everyone (allows read/write access)
    • Communication site for publishing information (allows read only access)

Yes, this may lead to more sites and Teams. Yes, this may lead to more tickets from users who at private site wanted to break permissions as usual and share list or library or folder with everyone. Yes, we would need to develop automation that can help manage the scale. But that’s a worthwhile trade-off for reducing oversharing!

More to consider

Large Custom Security Groups

There might be Large Custom Security Groups in tenant. What if the user wants to share site with one of these Large Custom Security Groups? What kind of site that would be? Private? Public?

Consider the following. When a team owner adds a security group to team members – it’s not a group added, but individual users. That makes sense – all team members can clearly see who are the other team members. That makes the team private. Private team should not be additionally shared at SharePoint site level. Only permissions should be provided through team.

Public team – as well as public standalone site – can be shared with EEEU. But what if the requirements are not to share the site with “Everyone…” but share with some other Large Custom Security Group – e.g. “All employee” or “All Central Office Users”? Can we do it? Should site be private or public in this case?
My opinion: site should be labelled as public. Site owner can request a public standalone site or create a team self-service, then site owner can remove “Everyone…” group from permissions and add a custom security group at any level.

Some orgs choose to recommend providing access to the standalone SharePoint sites via security groups vs SharePoint groups. So it is possible we have a private standalone site with access provided to security group (or m365 group). This is where an or should have their own policy – how big the group should be to be considered as large group and trigger site label as public. There are also dynamic security groups.

Automation Requirements

To support this model, we’ll need (at least) the following custom-designed solutions:

  • Automated Site Provisioning: A request-and-approval process for creating labeled standalone sites.
  • Channel Monitoring: A custom solution to detect and flag private/shared channels under public Teams, since there’s no out-of-the-box enforcement.
  • Large Custom Security Groups Monitoring: make a list of large custom security groups users can share information with – and check on scheduled bases – if the site is shared with large custom security group – site must be labelled as public.
  • Sharing site with “Everyone except external users” : If user accidentally removes “Everyone except external users” from public site – there must be an option for user to add “Everyone except external users” with permissions Read or Edit. Site can be shared with “Everyone except external users” only at the root site level and only if site labelled as Public.

Environment Clean-Up

To prevent oversharing, we should not only “from now on” follow the strategy described above, but also make sure our existing sites are compliant with our governance. This would be another challenge.

References

SharePoint Inactive Site Policies

SharePoint Advanced Management includes Inactive Site Policies under Site lifecycle management. Effective content lifecycle management is a key pillar of SharePoint governance. It plays a vital role in optimizing storage, preserving data integrity, and ensuring regulatory compliance. By systematically removing inactive or outdated sites, it also enhances security. Additionally, it supports successful Copilot implementation by ensuring that the information accessed is both accurate and current. So, how exactly this Inactive site policy works and what is the difference between Entra Id groups expiration policy and SharePoint Inactive Site Policy.

SharePoint Inactive Site Policy vs m365 Groups Expiration Policy

The Groups Expiration Policy has been a feature of Azure AD (Entra ID) for quite some time. It is included at no additional cost. This policy automatically notifies group owners about upcoming expirations and provides options to renew or delete the group. Since all self-created Teams teams and Viva Engage communities are backed by SharePoint sites and managed through Microsoft 365 Groups, this policy also plays a significant role in SharePoint governance ensuring that information stored in SharePoint remains current and properly maintained. I have an article Microsoft 365 group expiration policy deep dive.

Inactive Site Policy is a feature of SharePoint Advanced Management (SAM), which is an add-on and require premium SharePoint license. It also Identifies inactive sites, Sends notifications to site owners and can automatically archive or make sites read-only. Sound like very similar to to groups expiration policy.

Key differences

Inactive site policy user experience

Here is how the email notification looks like:

Note that

The email subject includes “Action required” and site title (name).
It always says “… has been inactive for more than a month” even if the policy configured for “6 months”.
It shows SharePoint logo, which might mislead “teams-oriented” users.
Site title is not clickable, so site admin/owner cannot just click site link but have to navigate to site manually.
When user clicks button “Certify site” – a message “The action completed successfully” pops up at the bottom of the email for a few seconds and then disappears. The email itself does not change, so when a user opens the same email again – there is no visual evidences the action was taken.

At the bottom of the email Microsoft mentions tenant name.

The email template is the same for all kinds of policies – it does not matter if the policy action is configured configured as “do nothing”, or to automatically enforce archive site or set it to read-only. I.e. email just says “Select Certify site to confirm if it’s still in use, or consider deleting it if the site is no longer needed.”. Email does not inform users that site will be set to read-only or archived.

Also there is no link where a user can get more info on the subject, but Microsoft says that inactive sites policy email template will be customizable – in the Site lifecycle management policies v2 expected summer 2025.

Admin – Inactive sites report

You can download a csv report of inactive sites generated by policy.
Report includes fields:
Site name, URL, Template, Connected to Teams, Sensitivity label, Retention Policy, Site lock state, Last activity date (UTC), Site creation date (UTC), Storage used (GB), Number of site owners, Email address of site owners, Number of site admins, Email address of site admins, Action status, Total notifications count, Action taken on (UTC), Duration in Read-Only.

There is no GUI to see the list of inactive sites (you can only download a csv file), but there is a magic button “Get AI insights”.

Get AI insights

Here are insights I have seen so far:

  • Inactive sites with significant storage usage
  • Multiple sites owned by the same account
  • Sites with Multiple Owners
  • Sites inactive for over a year

Inactive sites policy behavior

Policy sends emails immediately after policy activation. That means if you have thousands of inactive sites you might hit a 10k exchange limit of daily emails sent.

If a user owns multiple inactive sites – he/she will get multiple emails.

You can scope the policy down by site template, sensitivity label and creation source if you want different behavior for different types of sites, e.g. if you want to setup longer period of inactivity for one type of sites and shorter for others… not sure when it makes sense…

Implementing an Inactive sites policy

First of all – It is highly recommended to take care of ownerless sites (find owners) before triggering an Inactive sites policy.

If you have a relatively new tenant – you probably have not much inactive sites, so turning the policy on should not be a problem. The older your tenant is the more inactive sites you have. For older tenants you probably already have a lot of inactive sites – ant that could be a problem. So we’d need to take care of initial policy implementation, and after some time it will just work so we could forget about it.

There is no way to pilot this policy with pre-selected scope of sites or users. You can scope the policy down by site template, sensitivity label and creation source, but you cannot scope the policy down the way only sites or uses you want to be a testers or pilot project members will be the target of the policy.

In small orgs there should be no problems implementing this policy. Still I would start from just getting a report. There is a “How long after the last activity should a site be considered inactive?” configuration, so I’d start from the longest – 6 months, then move to the shortest you need. Medium orgs could get some ideas from recommendations to large orgs below.

In large orgs you might

  • trigger a spike in number of tickets submitted by users who needs help
  • hit a maximum sending limit with Exchange Online which is 10,000 email recipients per day

So it would be crucial for enterprises to avoid an initial surge and start from smaller number of recipients, and gradually let the policy work at a full strength. One of the options to achieve that would be

  1. configure the policy for reports only, get inactive sites report
  2. select sites owner and admins in a separate list – then select only unique ones – so every user will get only one email, split this list into small chunks
  3. communicate to site owners (by chunks) – using enterprise-approved “send from” email and enterprise-branded email template saying that the policy is gonna be implemented, you might receive an email (like this one – screenshot), you can trust this email and click buttons. A list of site urls user owns must be included in the email, so user could visit these sites
    (Optionally) you can instruct users how they can delete sites if site is no longer needed or archive sites if they are not sure if it is still needed or not

If so – it’d

  • forewarn users so they would know to do and not be surprised and would create less tickets
  • users might choose to delete or archive sites which would also
  • users would visit their inactive sites and trigger sites activity, and that should dramatically decrease number of emails sent to users initially, on the day one of policy implementation
    ideally – if users visit all sites – you’d have no inactive sites, so you’d just turn the policy on with no fear

then you’d wait for a couple of weeks, get new report to ensure that you have much less inactive sites – and you’d just enable the inactive sites policy (starting from the longest period – 6 month of inactivity)

References

Content Shared with Everyone: Access Review

This article is for SharePoint or Microsoft 365 admins focusing on governance and information protection. If you have SharePoint Advanced Management (SAM) – aka SharePoint Premium licensed or you got at least one Copilot for Microsoft 365 license (as having m365 Copilot license automatically enables SharePoint Advanced Management in tenant), then under reports – Data access governance (in SharePoint admin center) – you can not only get Content shared with ‘Everyone except external users’ (EEEU) reports, but also initiate access review. Let us look more closely at this functionality and discuss the pros and cons..

I’ll not repeat Microsoft documents:
SharePoint Advanced Management
Content shared with ‘Everyone except external users’ (EEEU) reports
Site access reviews for Data access governance reports
but I’ll focus on what is not there and a real-world experience.

Reports

First of all, report does not provide you with all SharePoint content shared with “Everyone except external users”. Report helps you with what was shared with EEEU in the last 28 days. That drastically limits usage of this feature. I.e. you should first get initial report on the all content shared with EEEU, and somehow take care of it by other means (consider How to Find Content Shared with Everyone in SharePoint and Teams), and only then you can use this Microsoft’s content shared with EEEU report and access review.

You can share content with EEEU or directly – by adding EEEU to resource permissions directly or by including EEEU into SharePoint group. So content shared with EEEU reports come in two flavors – “Specific files, folders and lists” and “Site membership”

“Specific files, folders and lists” user experience

When you initiate access review from the “Specific files, folders and lists” type of report – users (site admins/owners) get email notification that says “You have sites with specific files, folders or lists shared with ‘Everyone except external users’. This means everyone in your organization has access to this content. Review the items shared for potential oversharing and manage their access.

Content Shared with Everyone: Access Review - notification email example

Scrolling down, in the email, site owner can see a list (table) of incompliant sites with the following columns: Site name, privacy, sensitivity, external sharing and “Items shared”. Site name is clickable and sends user to the root of the site.

Below the list of sites there is a button “View shared items” that sends user to the special system page –
“https://orgname.sharepoint.com/teams/site01/_layouts/15/siteaccessreview.aspx/<id>” where he/she can see list of SharePoint items shared with EEEU. Columns are: (item) Name, Shared on (date), Shared by (email), Action (manage access). Item name and manage access are clickable.

Content Shared with Everyone: Access Review - user experience - siteaccessreview.aspx page example

If an item is a library item – e.g. document or a folder – it is displayed correctly – with icon according to the doc type and doc name. Clicking on the doc name – an actual document opens so you can review it’s content.

If item is a list item – it is displayed incorrectly – no icon, no meaningful info about the item (it is displayed as “”). Clicking on the link – a warning icon and message “Can’t preview this file. Open the file or download it to view in your desktop app”. Buttons “Open” and “Download” are there but not helpful as well.

Clicking on “Manage access” opens almost standard “Manage access” dialogue you can have via “manage access” item context menu, but with no “…” more options at the top right:

which makes this dialogue screen useless, as you can only provide additional access to the item or remove all access. You cannot remove EEEU from access without three dots “More options”.

Manage Access from the Policy:

Regular Manage Access:

“Stop sharing” literally removes all permissions to the item except owners

Under the “Groups” tab – you’d see that the item is shared with “Everyone except external users” but you will not be able to remove just this group from access…

By clicking on a group name – site owner will be able to change this group permissions, but the option “No direct access” is not selectable…

“Site membership” user experience

In the case with a “Site membership” report, text would be slightly different: “You have sites where ‘Everyone except external users’ has been added to the site membership. This means everyone in your organization has access to this site. Review site permissions for potential oversharing and manage access.“, which makes sense.

Right after that, in the email, site owner can see a list of incompliant sites with the following columns: Site name, privacy, sensitivity, external sharing and “Groups with org-wide access”. Site name is clickable and sends user to the root of the site.

content shared with EEEU access review  - Site membership user experience - You have sites where  'Everyone except external users' has been added to the site membership. This means everyone in your organization has access to this site. Review site permissions for potential oversharing and manage access.

Then there is a button “View SharePoint groups” that sends user to the special system page –
“https://orgname.sharepoint.com/teams/site01/_layouts/15/siteaccessreview.aspx/<id>” where he/she can see list of SharePoint groups (clickable) with EEEU as members.

By clicking on a group name – admin opens standard SharePoint “People and Group” membership page:
/_layouts/15/people.aspx?MembershipGroupId=X, which is nice, because from this screed a site owner can simply remove this group from the access list using Actions-> Remove:

siteaccessreview.aspx page

User can navigate directly to the reviews page:
“https://orgname.sharepoint.com/teams/site01/_layouts/15/siteaccessreview.aspx” and if there were reviews initiated by SharePoint admins – and it’ll work – admin will see all access reviews initiated for this site – columns are: Review name, Description, Requested on (date), Status, reviewed by (email) and admin comment. In case no reviews were initiated against tie site – “You have no reviews to take action on” will be displayed. That’s good.

Complete review

On the bottom of the siteaccessreview.aspx page you’ll see “Complete review”

Click on it, add comment (optionally) and confirm:

SharePoint Admin is able to see the status of every site access review stats – pending or completed – in GUI and in the .CSV report saved.

Admin experience: GUI only

Once you got report – you can initiate access review. All must be done in GUI, click-click-click selecting sites… But what if you have thousands? There is no PowerShell cmdlets or API for this functionality, which really limits your ability to implement it gracefully, especially in large Microsoft 365 environments and automate it.

Download detailed report

Report “Specific files/folders/lists…” does not include files, folders, list – i.e. it does not include what exactly is shared with EEEU. Report includes site id, url, name, template, is it teams-connected, sensitivity (?), privacy, external sharing, primary admin name and email, and number of items (?) shared with EEEU.

So technically you can communicate to site owners, but you’d need to rely on them to figure out what content is shared with everyone.

Email template

When you initiate Site access review – an e-mail notification is send to site owners. This e-mail is not customizable at all. The only admin can do is to add a message (for every “initiate Site access review” action). But the email looks really similar to the site lifecycle policies email notification, and Microsoft is working on version 2 of the policies with a customizable email template.

This email comes from “SharePoint Online <no-reply@sharepointonline>” address (not customizable), so comes “from outside of your organization” and can be considered as scam.

Microsoft’s logos and other graphics are blocked by default and e-mail includes a button “View shared items” – enough red flags for users to consider it as spam. Keep this in mind.

The good news is e-mail contains site name – so site owner can recognize it at act accordingly.

Usage scenarios

Small tenants

In small Microsoft 365 environments – yes, this functionality probably can be used “as is” (and should be used). Especially for new tenants – I’d recommend enable reports and use this feature on a regular basis.

Medium-size tenants

I’m not sure. It depends on your governance rules and company culture.

Enterprises

I’m very pessimistic if this functionality is useful in large environments. Reasons are:

  • if your tenant is not new – you already have a lot of overshared content, so you still need to come up with your custom solution (idk – PowerShell scripts?) to deal with oversharing. But once you designed your custom solution – why don’t you continue to use it?
  • In enterprises usually all the communication must follow approved templates, branding and so on.
  • User experience of reviewing shares with everyone… and managing permissions designed very poorly… In enterprise you do not want to deal with thousands of tickets from site owners who could not figure it out
  • In enterprises you’d think of automation

SharePoint Advanced Management

SharePoint Advanced Management is an add-on to Microsoft 365. Microsoft says that it is a powerful suite of tools for IT admins to bolster content governance throughout the Microsoft Copilot deployment journey. Let us have a closer look at what SharePoint Advanced Management (SAM) is how exactly it helps with governance enforcement in the Copilot era.

Microsoft classifies SAM’s features as “Manage content sprawl”, “Manage content lifecycle”, “Manage permissions and access”. I’d put SAM’s tools into these buckets: Reports, Policies, Search, Features.

SAM Reports

Reports are something that provides you with data, so you can analyze these date and use them to build/update your own governance strategy and maybe take some immediate action. Reports available are:

  • Change history reports
    you can choose org-wide or site-level settings, specify date range, sites and all or specific admins
  • Enterprise App Insights
  • OneDrive Accounts report
  • Data Access Governance (3 different ones)
    • Sharing Links with 3 pre-configured reports:
      Anyone links, People in your org links and Specific People links shared externally
    • Sensitivity labels applied to files: select label -> generate report
    • Content Shared with Everyone Except External Users:
      to discover specific sites whose content was made accessible for EEEU
      you can choose from two types of report: where specific files/folders/lists are shared with EEEU or “Site membership” where EEEU was added as a member and initialize access review
      (see Deep Dive into SAM DAG Content shared with EEEU access review)

SAM Policies

Policies allows you to set some governance rules, so that rules will be applied automatically, with no or little your intervention. SharePoint Advanced Management policies are:

AI Insights – report feature that uses a language model to identify patterns and potential issues and provide actionable recommendations to solve issues

Features

Features are smaller that policies, more like an update to existing functionality.

  • Conditional access to SharePoint site policy
    This enhances existing conditional access Entra Id feature with the ability to apply the policy to SharePoint sites directly or via Site sensitivity label.
  • OneDrive access restriction
  • SharePoint site-level access restrictions
  • Block download policy
  • Your recent actions
  • Default sensitivity labels for document libraries
  • Site access review

SAM for Search

I put it separately:

  • restrict discovery of SharePoint sites and content
  • Restricted SharePoint search

TBP

Azure ACS retirement: Track down App-Only (ACS) apps

With Microsoft officially announcing the retirement of legacy Azure Access Control Services (ACS), SharePoint administrators are now racing against time. For over a decade, ACS-based permissions—commonly known as SharePoint app-only service principals—have been widely used, with countless tutorials and blog posts guiding users on how to implement them in their applications.

However, many of these ACS-based apps are still actively accessing SharePoint sites. When Microsoft eventually disables ACS, we want to avoid a scenario where critical business processes suddenly break and teams are left scrambling.

To stay ahead of this change, our goal is to identify all app-only principals still relying on ACS to access SharePoint. This includes gathering details about the apps, their owners, the sites they access, and the site owners. The ultimate objective is to proactively reach out to the responsible stakeholders, inform them about the upcoming retirement, and encourage them to migrate their solutions to modern authentication methods.

Technical details

What kind of apps we are talking about, specifically? I can see the following options:

  1. Apps that were registered in SharePoint via AppRegNew.aspx (aka SharePoint app-only service principals) and provided with permissions in SharePoint via AppInv.aspx
  2. Apps that were registered in Azure (Entra Id) and provided with permissions in SharePoint via AppInv.aspx

Let us start with pulling data, then I’ll provide step by step instructions how to discover App-Only apps, get these apps activity and actions need to be taken.

Techniques we can use to get data

  • analyze audit log to get events where apps are accessing sites
  • analyze audit log to get events where ACS permissions were provided to sites
  • get data from system that tracks request for new ACS permissions
  • use reports from admin center
  • use the PnP Microsoft 365 Assessment Tool 
  • get report on apps owners and permissions from from Entra Id

Let us deep dive into each data source to see if it is actually helps us to get ACS apps in use…

Audit log: apps accessing sites

Microsoft 365 audit log is supposed to save all events happening in Microsoft 365. It is available for admins via GUI, PowerShell Exchange Module and Graph API. GUI Search m365 audit log now lives under Microsoft Purview – Solutions – Audit.

GUI search Audit Log under Purview

Unfortunately, when an App registered in Azure and provided with ACS access (via appinv) is accessing SharePoint sites – no events are saved in m365 audit log.

SharePoint app-only principals (apps registered in SharePoint via appregnew) are tracked in m365 audit log. Events would have a UserId “app@sharepoint” (yes, single user id for all apps). Other event details would include activity/operation (PageViewed, FileModified etc.), Item (full Url of a document or page etc.), AppAccessContext (includes ClientAppid, ClientAppName), ApplicationId (yes, this is how we know what app access what url on the site), and many other details.

Get Audit Log via Microsoft Graph API

The following reports are available via MS Graph API (some as v1.0, others in preview only under beta):

Service principal sign-in activity

This report is available through the servicePrincipalSignInActivity resource type and details the sign-in activity for a service principal in your tenant. The sign-in activity can be delegated or application-only scenarios. For application-only scenarios, the application credential activity provides additional information on the credential usage.

Service principal sign-in activity report provides the following details for every service principal:

  • id,
  • appId,
  • lastSignInActivity,
  • delegatedClientSignInActivity,
  • delegatedResourceSignInActivity,
  • applicationAuthenticationClientSignInActivity,
  • applicationAuthenticationResourceSignInActivity

More on Service principal sign-in activity

Application credential sign-in activity

This report is available through the appCredentialSignInActivity resource type and details the usage of an app credential (secret, certificate, or federated identity credential) in your tenant.

Application credential sign-in activity report provides the following details for every service principal credential:

  • id, keyId, keyType, keyUsage,
  • appId, appObjectId, servicePrincipalObjectId,
  • resourceId,
  • credentialOrigin,
  • createdDateTime,
  • expirationDateTime,
  • signInActivity

More on Application credential sign-in activity

Audit log ACS permissions provided events

This is relatively easy. There are just two kinds of events that might help us to understand ACS usage in tenant:

SharePointAppPermissionOperation

Pull audit logs with record type is SharePointAppPermissionOperation so you’d get events where permissions were provided to apps. Operation type (activity) would be like AppPermissionGrant.

Microsoft started logging this record type not long ago and there is no documentation found (as of Feb 2025). So the only I noticed that might help is:

  • if user id is “app@sharepoint” – that indicates Sites.Selected permissions were provided to the app
    (e.g. via Grant-PnPAzureADAppSitePermission )
    under “AppId” you’d have an app (client) id of the client app (permissions provided to) in the form of
    “i:0i.t|ms.sp.ext|<appId>@<tenantId>”
    under “ApplicationId” and “AppAccessContext – ClientAppId” – you’d have an app (client) id of the admin app (permissions provided via)
    ApplicationDisplayName would contain the display name of the admin app
    Other fields: RecordType 205, UserType 5, AuthenticationType OAuth
  • if user id is one of your actual user’s account in tenant – that indicates ACS permissions were provided to the app (e.g. via appinv.aspx page at SharePoint site)
    under “AppId” you’d have an app (client) id of the client app (permissions provided to) in the form of
    “i:0i.t|ms.sp.ext|<appId>@<tenantId>”
    there would be no “ApplicationId” field and under “AppAccessContext” no ClientAppId
    ApplicationDisplayName Unknown
    Other fields: RecordType 205, UserType 0, AuthenticationType FormsCookieAuth

Appregnew.aspx and appinv.aspx pages viewed

You can pull audit logs with record type is SharePoint and activity type (operation) is PageViewed and keyword for free search is appregnew. You’d get events when there was an attempt to register a new SharePoint app-only service principal.

The same but with appinv as a search keyword – to get events when there was an attempt to provide ACS permissions for a SharePoint app-only service principal or for an Azure App registration.

In both cases we know that there was an intention to have a principal with an ACS access. We can reach these people to inform that ACS is deprecated and so and so. Worst scenario – we notify somebody who already know that.

Some time ago (around mid – 2023) Microsoft by default disabled ability for site owners registering apps and providing permissions in SharePoint via Appregnew.aspx and appinv.aspx. So since then only SharePoint service admins could provide ACS permissions to apps. In this case you’d check with your request tracking system – to whom ACS were provided.

System that tracks request for new ACS permissions

In case you have a process of providing ACS permissions… Process might include tickets to service desk or similar kind of system… Anyway – check if you can get data from that system – like who requested for what app to what site etc…

Reports available from Microsoft 365 Admin Center

So far the only report that might help is in development (see Microsoft 365 Roadmap – feature Id 417481) and scheduled to be available in May 2025. So far (July 2025) what I can see is the report is not working.

“Enterprise Application Insights is a powerful report which helps SharePoint Administrators to discover all the SharePoint sites that are allowed access by third-party applications registered in your tenant. The report also provides details on the application’s permission and requests count to help admins take further action to strengthen the security of the site. It is part of SharePoint Advanced Management capabilities.”

The feature is already documented here: Generate App insights reports and is seems like the report will not be available for all tenants – but just for tenants with Microsoft SharePoint Premium (SharePoint Advanced Management) or Copilot license assigned.

PnP Microsoft 365 Assessment Tool 

Microsoft 365 Assessment Tool is an utility designed by PnP team a while ago and since then serves SharePoint admins very well. In particular, it helps us identify and evaluate the Azure ACS usage for tenant by providing the usage data of ACS principals, and even generating a Power BI reports.

If you run this tool specifying AddInsACS mode, it provides you with:

  • classicacsprincipals.csv report that includes all apps with access to SharePoint. Details are: App Ids, if the app has Tenant or Site Collection Scoped Permissions, if the app Allows AppOnly, RedirectUri, AppDomains and ValidUntil
    If the ValidUntil field contains specific date – that means the app was registered via appregnew
    If the ValidUntil field contains “01/01/0001 00:00:00” date – that means the app was registered in EntraId
    if the AllowAppOnly field equals TRUE – that means ACS permissions were provided to the app
  • classicacsprincipalsites.csv – report contains apps and sites they have access to
    Details are: AppIdentifier, ServerRelativeUrl
  • classicacsprincipalsitescopedpermissions.csv – list of apps permissions to sites
    Details: AppIdentifier, ServerRelativeUrl, SiteId, WebId, ListId, Right (Read/Write/FullControl/Guest etc.)
    If the WebId field equals zeros, that means permissions were provided to entire site collection
  • classicacsprincipaltenantcopedpermissions.csv – list of apps with tenant-wide permissions
  • some other reports, like list of sites, list of webs

Unfortunately, this tool does not provide when the app was last time authenticated or when the app accessed the site. Also, we do not know what kind of access was provided for the app to the site – Sites.Selected or ACS. If at least one access provided for the app was ACS-based – the app will have AllowAppOnly field equals TRUE.

The tool is highly recommended to use: SharePoint Add-In and Azure ACS Assessment

Report on apps owners and permissions from from Entra Id

Using all the methods above – you’d get a list of active service principals that use legacy ACS authentication. But to whom we need communicate to regarding this service principals? Obviously, we are looking for these service principals owners and sites owners.

There are multiple options how to get an app owner from Azure (Entra Id):

Getting sites (teams, groups) owners is a separate challenge – you’d need or a 3-rd party app or a set of custom PowerShell scripts (see How to Get SharePoint and Teams sites owners report with PowerShell).

How to inventory ACS apps (App-Only principals) and get their activity

The most effective way would be

  • Use Microsoft 365 assessment tool to gel list of apps that allows AppOnly access
  • Use servicePrincipalSignInActivity or appCredentialSignInActivity to get last Sign-In Activity

I use the following PowerShell to start the tool, get status and export reports:

$tenantDomain = "" # "contoso.sharepoint.com"
$clientid = "" #
$certThumbprint = ""
$certPath = "My|CurrentUser|" + $certThumbprint

./microsoft365-assessment.exe start --mode AddInsACS --authmode application --tenant $tenantDomain --applicationid $clientid --certpath $certPath

./microsoft365-assessment.exe status

./microsoft365-assessment.exe report --id <report id> --mode CsvOnly --path ".\ACS-reports"

So you’ll get a list of legacy apps sorted by recent activity. These apps need to be decommissioned. There should be no one App-only service principal or app registration (client id) with legacy ACS permissions provided in tenant.

Communicate to apps owners and site owners

Once you get a list of legacy (ACS/App-Only) apps – pull report on these apps owners.
Having “classicacsprincipalsites.csv” report from m365 assessment tool – you can pull site owners for every app you need to decommission. This is a big topic itself. See details in my article How to prepare your tenant for Azure ACS retirement – Guide for SharePoint Admins


More Observations

Test scenario 1
DisableCustomAppAuthentication is true, i.e. ACS are not allowed in tenant.
SiteOwnerManageLegacyServicePrincipalEnabled -s false, i.e. site owners cannot register apps at sites or provide permissions to app on sites.
It is not possible for admin to go to appregnew.aspx and create an app (app-only spn).
I registered apps in Azure.
It is possible for admin to go to appinv.aspx and “provide” permissions to the azure app registrations.

Connect-PnPOnline works with certificates or with secrets.
Get-PnPSite works only if connection was made with a Certificate (if connection was made with secret – it gives 401 unauthorized).

Test scenario 2
DisableCustomAppAuthentication is false, i.e. ACS are allowed in tenant.
SiteOwnerManageLegacyServicePrincipalEnabled -s false, i.e. site owners cannot register apps at sites or provide permissions to app on sites.
Connect-PnPOnline and Get-PnPSite works with certificates or secrets if ACS access was provided for an app to at least one site.
If there was no ACS permissions provided for the app – Get-PnPSite gives “Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))”

Error messages and possible fixes

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))” – happens if you try to access SharePoint API with an Entra Id app registration that have an API permissions but do not have legacy ACS permissions being authenticated with a secret.
Solution option 1: try authentication with a certificate.
Solution option 2: use Microsoft Graph API.

The remote server returned an error: (401) Unauthorized.” – happens if you try to access SharePoint API being authenticated with a certificate with an app registration that do not have modern API permissions correctly provided.
Solution: ensure app registration is configured with SharePoint API permissions.

(403) Forbidden” – happens if you try to access SharePoint API being authenticated with a secret with an app registration that do not have modern API permissions correctly provided.
Solution: ensure app registration is configured with Graph API permissions.

AccessDenied”,”Either scp or roles claim need to be present in the token.” – happens if you try to access Graph API being authenticated with a secret with an app registration that do not have modern API permissions correctly provided.
Solution: ensure app registration is configured with Graph API permissions.

Get-MgServicePrincipal

Get-MgServicePrincipal returns servicePrincipal objects with properties and relationships.
ServicePrincipalType = ‘Legacy’ indicates service principal was registered in SharePoint (via appregnew.aspx).

An issue with ACS apps discovery when Graph permissions also provided

There was an issue (before late June 2025)

How do we know the ACS permissions are provided for the app to the site? Two great options: appprincipals.aspx and Microsoft 365 assessment tool by PnP.

An app is shown under appprincipals.aspx only in case if ACS access was provided to app but Sites.Selected access was not provided. The moment you provide Sites.Selected access for the app to the site – the app disappears from list of apps under appprincipals.aspx page. The app is not visible for Get-PnPAzureACSPrincipal. PnP M365 Assessment Tool also fails to get list of ACS apps if the site also has Sites.Selected permissions. It does not help if you remove Sites.Selected permissions. This issue is reported to Microsoft and confirmed. Microsoft is working on it. Upd (June 2025) – Microsoft implemented fix, so all should be good now (but if you are seeing “Sorry, something went wrong” trying to access appprincipals.aspx – just wait, they said db needs to be updated as well, it takes time).

A fix, current state and changes

Microsoft deployed a fix and updated databases. So starting July 2025 we can see all apps (legacy, modern, with ACS and with Graph permissions assigned) under appprincipals.aspx page. The good is we finally can see apps, the bad is we cannot differentiate – is this an ACS app or app with permissions provided via Microsoft Graph, also we cannot see permissions.

Microsoft 365 Assessment Tool does a good job, detecting if the app allows App-Only permissions (AllowAppOnly equals true in the report classicacsprincipals.csv). Under reports classicacsprincipalsites.csv and classicacsprincipalsitescopedpermissions.csv, the tool provides what sites every app has access to and what permissions the app has, but again, it does not provide details if permissions were provided with ACS or Microsoft Graph.

References

Azure ACS retirement: How to prepare your tenant – Guide for SharePoint Admins

Microsoft announced EOL of ACS, and we as SharePoint administrators must take actions. ACS retirement as is a really big deal – entire era of SharePoint app-only service principals will be gone. SharePoint developers used ACS apps since 2013 to build solutions, and when it comes to software development – it always takes time. Imaging the code that was designed for ACS now needs to be reviewed and re-written to adopt changes, then re-compiled, re-tested, re-deployed etc. So it is critical that we should take measures now to avoid bigger issues in April 2026.

Recommended transition tactics: for developers

  • Get a new App Registration in Azure (Entra Id) with Sites.Selected permissions, ensure no ACS permissions provided to the app (see details on Sites.Selected) and use it
  • Prioritize using Microsoft Graph API
  • If Graph API does not provide required functionality – it’s ok to use SharePoint API, but keep in mind in this case certificate should be used (not secret) for authentication

Recommended transition tactics: for SharePoint admins

High-level recommended steps are:

  • Keep saving audit logs
  • Encourage users and developers to register applications in Azure (not in SharePoint)
  • Start providing Sites.Selected permissions
  • Disable ability for site owners to use AppRegNew and AppInv
    Stop registering service principals via AppRegNew and providing ACS permissions via AppInv
  • Pull report on existing Apps that use ACS permissions
  • Notify developers and users of the ACS apps
  • Switch ACS off earlier than Microsoft

Thinkin on devs – keep in mind:
– ACS apps have a huge legacy – tons of articles and code examples and so on…
– Switching to a modern authentication method would require changes in code (though minor, but still), so developers must be engaged
– Any change in code would require another round of code compilation, testing, deploying etc.

That means it is not easy (sometimes it is not even possible) to adopt a new modern authentication method. It requires efforts and time, so you need to notify dev as earlier as possible. So it is crucial to complete steps above and start communicating to users as earlier as possible.

Detailed steps for SharePoint administrators:

Keep audit logs

This should be done in advance, but if you did not – starting today and until it’s over you’d get audit logs from Microsoft 365 purview center – consider selecting all events with record type SharePointAppPermissionOperation. Also might be helpful to keep events anyone visited appinv.aspx or appregnew.aspx page. Pull logs now starting with earliest available event (usually 90 days). Some audit logs are available only through Microsoft Graph API. See more details regarding audit logs for ACS tracking KBA.

Encourage users registering applications in Azure (not in SharePoint)

Creating App Registrations in Azure is usually not what SharePoint admins do. Sometimes users are allowed to register apps, sometimes it is blocked for a regular user and done by identity management (or so) but the main idea – users and developers should be able to get service principals (App Registrations) in Azure. Users would need Sites.Selected permissions consented (see more about Sites.Selected) or granular permissions consented (more on granular permissions to SharePoint).

Some pro’s of App Registered in Entra Id (vs SharePoint App-only service principals):
– It supports authentication with client secret and/or certificate, custom expiration time
– It supports both APIs – Microsoft Graph API and classic SharePoint REST API

Be prepared to instruct users how to get and use certificates in their app registrations.

Provide Sites.Selected permissions

99% of requests for application permissions to SharePoint would require access to a specific site (sites), or to a specific list/library/folder/file (but not to entire tenant). So consider providing Sites.Selected permissions by default (or granular permissions when they are in GA). Create a process so users can request permissions to SharePoint sites for their Azure-Registered Apps. Consider automation if you are a large company (here is one of the possible Sites.Selected automation solutions).

Inform user that ACS is deprecated and you do not provide any new ACS permissions.

Disable registering new service principals in SharePoint

Once you are good in providing non-ACS permissions, it’s time to disable registering service principals in SharePoint. Users should not be able to get a new SharePoint App-only service principals (apps that they used to get from SharePoint sites just going to AppRegNew.aspx).

Disable ability for site owners register service principals in SharePoint via appregnew.aspx is done via Set-SPOTenant PowerShell cmdlet:

Set-SPOTenant -SiteOwnerManageLegacyServicePrincipalEnabled $false

When the value is set to false, the service principal can only be created or updated by the SharePoint tenant admin. Using AppInv.aspx page will also be disabled for site owners. Your users will start seeing “Your SharePoint tenant admin doesn’t allow site collection admins…” message (see details), but that’s ok.

There might be rare cases when your in-house solutions or 3-rd party apps got their secrets expired and would require new legacy ACS-based permissions, it is tempting to allow ACS permissions as an exception (as technically it is possible for SharePoint service admin to provide ACS-based access to sites), but I would strictly discourage you to do so. If you decide to provide ACS – track this activity (so you know for whom this ACS-based permissions were provided).

Pull report on existing ACS Apps that use ACS permissions

You need to know who are your vulnerable clients – you should pull reports to get a list of existing Apps that use ACS permissions, apps owners, maybe sites these apps have access to and sites owners

You can get list of developers combining
– audit log data from Admin Center and Graph API
– report from Entra Id on apps and owners
– report from SharePoint sites on permissions provided for apps
– reports generated by PnP Microsoft 365 assessment tool

Here is the detailed KBA on how to get reports on legacy ACS service principals usage in tenant

Consider the following steps to get ACS apps owners

  • get ACS apps with permissions using Microsoft 365 assessment tool
  • pull these apps owners from Entra Id
  • using Graph API audit logs data – mark apps active/inactive based on date of the latest login

Notify developers and users of the ACS apps

From the step above we can have a lost of legacy ACS apps and their owners, as well as apps activity (last login), so we can start communicating developers (app owners):

  • As earlier as possible – e.g. in March-April 2025 (1 year before ACS EOL), notify all apps owners that they need to transition to Azure apps and Selected permissions
  • Get ACS apps activity and repeat communication, including active app owners
  • Get ACS apps activity and repeat communication, including owners of sites apps still have access to
  • Communicate to all apps owners that there will be a temporary and permanent shut down of ACS (see below)
  • I case you have ACS apps with tenant-level permissions – communicate to them separately

    Switch ACS off earlier than Microsoft

    You need to plan actual ACS apps disablement in tenant in advance – earlier than Microsoft will do it (in case Microsoft will not put it off). Also consider temporary switch off ACS (“scream test”) even earlier, let say, starting September 2025.

    Temporary and permanent ACS disablements before official ACS EOL are needed as scream tests – in case there are users who ignored all communications and still use ACS apps. Disabling ACS early may cause problems with existing applications, but it is necessary to avoid more serious consequences when the time comes for Microsoft to turn it off. So be prepared to handle tickets and communicate to apps owners in advance.

    This might be your draft plan:

    • schedule the first and 2nd temporary (e.g. during 1 hour) ACS apps disablement ~ 6 and 5 months before EOL
    • schedule the 3rd and 4th temporary (e.g. during 24 hours) ACS apps disablement ~ 4 and 3 months before EOL
    • schedule the full (permanent) ACS apps disablement ~ 2 months before EOL

    References

    Restricted SharePoint Search Deep Dive

    Restricted SharePoint Search is a new Microsoft feature to mitigate sites oversharing issue when you are implementing Copilot. The feature is documented here, but still I have some questions, e.g.:

    • How about external data? Copilot can use external data to learn from via agents and connectors. But would Restricted SharePoint Search if implemented allow data from external connectors to be used in copilot?
    • “Users’ OneDrive files, chats, emails, calendars they have access to” – means own data for every single user or all shared OD data?
    • What exactly is “Files from their frequently visited SharePoint sites”? I mean, how frequently user needs to visit site for this?
    • What exactly means “Files that the users viewed, edited, or created.”
    • What about teams chat messages, e-mails, viva engage messages?
    • “Files that were shared directly with the users” – does that mean “individual files shared” or can include folders, libraries, sites?
    • If user is a member of a teams – would all team content included?
    • It says “Files…” but would site pages be included? Or list items? Or list items attachments? Pages is something that people use to create wiki to share knowledge.
    • How long it takes for Microsoft 365 to start restricting results after Restricted SharePoint Search is enabled
    • How to deal with “You do not have the required license to perform this operation”

    Here I’m going to answer the questions above.

    So far I build a test scenario using my dev tenant that includes multiple collaborated users and content in the form of files, pages, list items and messages spreaded across multiple sites falling into different categories of Restricted SharePoint Search allowed content.

    You do not have the required license…

    If you are getting “You do not have the required license to perform this operation” when you are trying Get-SPOTenantRestrictedSearchMode or Get-PnPTenantRestrictedSearchMode – that means there is no Copilot for Microsoft 365 licenses assigned to tenant yet. This feature – Restricted SharePoint Search – works only when at least one Copilot license is assigned to tenant.

    … TBC

    References