TBP
Category Archives: Azure
Implementing Microsoft 365 group expiration policy in large companies
WIP
Scenario
Let say you administer a large Microsoft 365 environment (e.g. ~100k+ users and/or ~50K+ sites) and after some years you have a lot of ownerless groups and sites (around 5k probably), and a lot of inactive groups and sites (maybe 15k). And new ownerless groups are coming at a pace of dozens per week? You a thinking of stopping bleeding and cleaning this up…
Out-of-the-box we have Microsoft 365 groups expiration policy and Microsoft 365 ownerless groups policy. You might also have some 3-rd party tools implemented – e.g. ShareGate, SysKit.
If you do not care – you might just activate both OotB Microsoft policies – via GUI – they are simple to activate. But once you activated policies – they will trigger thousands of emails. Now imagine a person is getting dozens of emails asking him/her to be an owner or to renew the group that maybe does not make much sense… What’ll happen? Right, people will probably ignore these notifications. What will happen next? Groups and sites will be automatically deleted. And then? Right, there will be a noise and many angry users and high-priority tickets and you will have to restore sites/teams and finally you’ll have to look for groups owners manually.
So, what is the right way to clean-up a large Microsoft 365 environment from ownerless and inactive teams, groups sites?
Not a trivial question, hah?
Solution
TBP
Implementing Microsoft 365 groups expiration policy
If you are thinking of activating in an existing environment – you would probably have a spike – all the old groups will be subject to policy. The ide is to avoid situation when a specific person – group owner will get dozens of email. It would be better if a person will receieve, let say one email per week.
Here is my 4 possible approaches to avoid this spike, distribute notifications evenly across the time and ease the pain:
By changing Group Lifetime
You would need to change the policy every, e.g. week, specifying different group lifetime in days period. Consider
– calculate number of days between the oldest group created an today, plus 35 days – it’ll be your first “group lifetime”
– activate the policy with this number of days in “group lifetime” – and within a week you will get notifications on the oldest group/groups
– after a week or two – change the “group lifetime” decreasing it by e.g. 30-60 days and reactivate the policy… and so on
You can easily calculate it all and choose your pace depending on how many groups you have to renew, how much time you need to clean-up. You got the idea.
Downside – in the email notification it will be said “otherwise the group will be deleted on …”, but once you start joggling with dates – this will not be true probably.
By renewing groups as admin
tbp
By sending customized e-mails to users
tbp
By sending users to the groups page
tbp
Microsoft 365 group expiration policy deep dive
Nobody likes garbage, including Microsoft 365 administrators. If any user can create a team or yammer community – they create, but then they leave company and we are getting more and more abandoned groups, teams and SharePoint sites. So we need a way to clean up environment. There is a Microsoft 365 groups expiration policy that can help remove unused groups from the system, but since all Teams and Yammer sites are group-based – it also helps SharePoint admins make things cleaner.
Who can configure the policy and how
The policy lives under Azure Portal, Azure Active Directory, Groups, Expiration:

Microsoft 365 groups expiration policy can be configured by Groups Admin or Global Admin (tenant admin) only. Microsoft 365 Teams or SharePoint admin cannot configure it. Microsoft says that User administrator can do it – so I need to verify it.

Here is the policy config screen:

Microsoft documented it well in the “Microsoft 365 group expiration policy“, but I completed some tests in my lab environment and here is what I found and what is not covered by Microsoft. Let me share it with Questions and Answers format:
Questions and Answers
General questions
Q: How long it takes for policy to start generating notification emails after activation?
A: Immediately, i.e. minutes, maybe up to one hour (in case there groups that are subject for the policy).
Q: Can I customize email that is send to group owners?
A: No, there is no such option at the moment.
Q: What is the email address notifications come from?
A: It’s “msgroupsteam@microsoft.com” with the display name “Microsoft Groups Team”
Q: What does a notification email look like?
A: Please find some examples below, in the end of this article.
Q: Are there any other ways to get notifications? Teams chat? Phone message?
A: I’m not aware of phone messages, but I have seen notification in teams: “TeamName is expiring soon. Renew now”:

but I got only one teams notification, though e-mails notifications I got many.
Q: What happens when a user clicks “Renew group” button in the email notification?
A: User will be sent to a Microsoft’s page and the following “Do you want to renew the group?” window will be shown:

On Yes, it says”<groupName> was successfully renewed. You can close this window now”:

And the group expiration date will be set up as current date.
On “No” it says “Group was not renewed. You can close this window now.”:

And an expiration day will not be changed. No more notifications will be generated. The group will be active until expiration date. Then the group will be deleted.
Q: What if two owners choose opposite?
A: The last action will take effect.
Q: what if one user choose “delete group” but the other one later decided “Renew group”?
A: The one who click “Renew group” will see “<Group Name> successfully renewed. Because the group was deleted, it might take up to 24 hours to be fully restored. You can close this window now.”

Q: What if the group does not have owners?
A: If the group does not have an owner, the expiration emails will go to the email specified in policy configuration. Usually it is a distribution list with admins or other responsible team.
Q: What if I deactivate the policy – will email notifications sent earlier still be actionable?
In other words, would users still be able to renew the group clicking on the “Renew group” button?
A: Yes. Actually “Renew group” button is just a link to the Url:https://account.activedirectory.windowsazure.com/Group/RenewGroup?tenantId=<tenantId>&id=<groupId>
where a group owner can renew group.
Q: If one of the owners renewed the group – what will happen with notifications sent to other owner? What if other owner click “Renew group” or “delete group”?
A: Notifications sent will stay. Since buttons in the email are just links (not actionable buttons) – user will be redirected to a web-page where he/she will be able to renew or delete the group.
Q: As per MS: “Groups that are actively in use are renewed automatically around 35 days before the group expires. In this case, the owner does not get any renewal notifications. Any of the following actions will automatically renew a group…<list of actions>”. So, what exactly does “Groups that are actively in use” mean?
A: This is not disclosed by Microsoft. They only say “Azure Active Directory (Azure AD), part of Microsoft Entra, uses intelligence to automatically renew groups based on whether they have been in recent use. This renewal decision is based on user activity in groups across Microsoft 365 services like Outlook, SharePoint, Teams, Yammer, and others.” Btw, <list of actions> includes almost all user actions – so basically any action – even just visit site/team is considered as activity.
Q: Can I track the policy in action via audit log?
A: There is no “activity type” for this policy’s specific actions… You also cannot specify user “msgroupsteam@microsoft.com” to get all activities. So no tracks on the policy “before action” – i.e. at the detection and e-mailing stage. If a user clicks “renew” button or “delete group” link – this should be logged as this user action. If it happens that the group is deleted by policy – this should be logged under policy’s account – I’ll follow up on this. TBC.
Q: After the group is deleted, who can restore it?
A: MS says: “A deleted Microsoft 365 group can be restored within 30 days by a group owner or by an Azure AD administrator”.
In fact, SharePoint admin,
Q: What if a user forward this e-mail notification to other user? Can this other user renew or delete the group?
A: When a user receive a notification email forwarded, and he/she click “Renew group” button – his/her experience will be the same if he/she is also a group owner. If a user is not a group owner – he/she will get “You don’t have permission to renew this group because you’re not an owner. To renew , contact a group owner. You can close this window now.”:

Note: if a user with active groups administration permissions receives email and try to renew or delete the group – he/she will also be able to do that.
Q: Can user get information on groups he/her owns, groups expiration data? Can user renew the group before the policy trigger email notification?
A: yes, all that can be done from the page: https://myaccount.microsoft.com/groups/groups-i-own
Scenario with many existing inactive groups
Let say we have a large Microsoft 365 environment with many inactive groups, some of them are inactive for a long time – e.g. 1 or 2 years. We want to implement groups expiration policy, but we want to understand better the policy behavior.
Microsoft says: “The expiration period begins when the group is created, or on the date it was last renewed” and “When you change the expiration policy, the service recalculates the expiration date for each group. It always starts counting from the date when the group was created, and then applies the new expiration policy.”
So in case we implement the policy first time, we know that Renewal Date for all groups is just a Group Creation Date.
Q: What will happen if I activate the policy – will the policy immediately start generating emails to the owners of inactive groups or the policy will wait for expiration period minus 30 days?
A: Immediately. Once activated – policy starts detecting expired groups and sending notifications.
Q: Which groups the policy will be triggered against? All or Inactive only?
A: As per Microsoft, if at around 35 days before expiration it will be determined that group is actually active, the policy can renew the group automatically.
But definition of this activity is not disclosed and might be not the same as group activity status 90 days based on MS Graph data you can see at CA.
(I got notifications for groups that were not active recently but with Active status).
Q: In the case above – what would be the deadline? When the policy will delete the group?
A: If the group expiration period is passed, but the policy was just activated – it does not delete the group immediately. Policy allows ~30-35 days for owners to renew the group.
E.g. My test policy was activated May 3 and I got message for old group immediately, but it said that the group will be deleted on June 7.
Q: What if there are more than 10K emails – will it trigger Exchange throttling?
A: Most likely emails not sent will be sent next day.
Q: Can I specify a distribution list in the policy as an “Email contact for groups with no owners”?
A: Yes
Q: Can I specify an external e-mail address as an “Email contact for groups with no owners”?
A: TBC
Q: Can admin ask user to renew or delete the group by some other custom solution (skipping the policy)?
A: yes. Actually, “Renew group” button is just a link to the following Url:https://account.activedirectory.windowsazure.com/Group/RenewGroup?tenantId=<tenantId>&id=<groupId>
where <tenantId> is tenant id and <groupId> is group Id. So basically anyone
Microsoft 365 Groups object model
Let me explain the policy behavior in m365 group object model terms.
There is a group property “RenewedDateTime”. When group is created – this property is set up to group created date/time (same as group CreatedDateTime property value).
For the notification purposes the policy calculates “Expected Expiration DateTime” as RenewedDateTime plus “Group LifeTime” (number of days specified in policy, e.g. 180). First notification is triggered about 30 days before “Expected Expiration DateTime”, so the policy simply selects groups with RenewedDateTime property value less then current DateTime minus “Group LifeTime days” minus 30 days and sends notification starting from oldest group:
RenewedDateTime < Today - GroupLifeTime -30
When owner confirms group is still needed – RenewedDateTime is setup to current DateTime.
Q: When a user chose to “Renew group” – will it impact group activity?
A: No. If a user did not visit group – but just clicked “Renew group” – it will not trigger group last activity date. E.g. inactive group will still be inactive.
Q: Is there an API to configure Microsoft 365 groups expiration policy programmatically?
A: Yes, in MS Graph API it is called Group Lifecycle Policy: groupLifecyclePolicy.
Q: Can I programmatically renew the group (all groups) as an admin?
A: Yes, consider using PowerShell 7 and PnP.PowerShell module.
PnP Doc says Reset-PnPMicrosoft365GroupExpiration command “Renews the Microsoft 365 Group by extending its expiration with the number of days defined in the group expiration policy set on the Azure Active Directory” – but that does not seem accurate. This command sets up “RenewedDateTime” group property to the current datetime, not related to current policy settings (the policy might even not have been activated).
Q: Is it possible to setup “RenewedDateTime” property to another date/time of my choice (not today)?
A: I could not find a way so far… It says Property 'renewedDateTime' is read-only and cannot be set.
Q: What permissions are required to renew the group with Reset-PnPMicrosoft365GroupExpiration?
A: TBD
Screenshots
Notification e-mail that comes to group owners “as is” – web outlook view:

Notification e-mail that comes to group owners when content is unblocked (web outlook):

Notification e-mail that comes to group owners when pictures are loaded (desktop Outlook):

Notification e-mail that comes to group owners some key areas:

And I’d add that e-mail says how many members in this group (number of members, not including owners… i.e. if you are the only owner – it’ll be zero members).
Correction: “Renew group” is not an actionable button – it is just a html button with a link.
Screenshot of the notification that comes to email specified in policy for the groups that does not have owners:

References
FastAPI on Azure Functions with Azure API Management
Following Pamela Fox tutorial “FastAPI on Azure Functions with Azure API Management“.
The idea is to deploy FastAPI to Azure Functions the way auto-generated interactive documentation would be public, but actual API would be protected. Pamela solved it with Azure API Management and subscription keys:
“One of my goals was to have the documentation be publicly viewable (with no key) but the FastAPI API calls themselves require a subscription key. That split was the trickiest part of this whole architecture, and it started at the API Management level.”
Pamela published it in 3 parts:
– the idea and solution explained under her blog: FastAPI on Azure Functions with Azure API Management
– code and some initial steps at GitHub: pamelafox/fastapi-azure-function-apim
– video with more deploying details at YouTube: Deploying FastAPI app to Azure Functions + API Management
I will just repeat all the steps in this one-pager.
Environment I use: Linux Ubuntu + VS Code with “Dev Containers” extension and azd
- Clone https://github.com/pamelafox/fastapi-azure-function-apim
- Start visual studio code and reopen the project with container
- ensure it works locally with
PYTHON_ISOLATE_WORKER_DEPENDENCIES=1 func host start
- Deploy it to Azure functions with (you’d answer questions):
$ azd auth login
$ azd init
$ azd up - Go to API management Service, Subscriptions, Add subscription, copy the key (secure it)
- From API management service, Overview – open Gateway URL and append it with “/public/docs”
- Try GET /generate_name as is – you’ll get “401”
- Try the same with subscription key – you’ll get “200”
- Save Request Url to call the API from your front-end app
Nest steps:
- calling other APIs
- connecting to Databases
- using secrets
Deploying Python FastAPI to Azure
PowerShell scripts for Microsoft 365 SharePoint
External Access Guest Access Microsoft 365 SharePoint Teams
I will be saving my personal gotchas on Microsoft 365 External Access and Guest Access in SharePoint and Teams
We configure external/guest access in AAD, m365 Admin Center, Teams Admin Center, SharePoint Admin Center, specific Group, Team or SharePoint site.
We can configure external guest access directly, or can configure sensitivity labels and policies in Purview (Compliance Admin Center). Configuring sensitivity labels for sites/groups we configure external guest access settings. Configuring sensitivity labels policies we apply labels.
External access via “All Users” group
Be careful with “All users” group created as part of the process.
Microsoft: “The dedicated All Users group includes all users in the directory, including guests and external users.” And indeed, “All Users” group by default include external users.
So here is the scenario: we have a site where external sharing is enabled, and someone is sharing a specific file1 or folder1 with some external users. The other site/group member is sharing another file2/folder2 with “All Users” assuming All Users means all this group member. This gives external users access to file2/folder2.
Remediation
Option 0: remove “All Users” group
Option 1: exclude External users or Guest users from “All Users” group:
(user.userPrincipalName -notContains "#EXT#@")
or
(user.userType -ne "Guest")
(explained here).
Option 2: schedule a job that removes “All Users” from all sites UIL. Optionally inform site owners not to use “All Users” but use “Everyone except external users”.
Sensitivity labels in Microsoft Teams, Microsoft 365 groups, and SharePoint sites
- Follow instructions in MS article:
- beware that “Connect-AzureAD” works only in Windows .net framework – i.e. PowerShell 5.1
if you try to run it in PowerShell 7 – you can get “Connect-AzureAD: One or more errors occurred. (Could not load type ‘System.Security.Cryptography.SHA256Cng’ from assembly ‘System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’.)” Error.
(check Connect-AzureAD Could not load type ‘System.Security.Cryptography.SHA256Cng’ from assembly)
Configuring Sensitivity Labels
Sensitivity labels are configured under Microsoft Purview (Compliance Center), Solutions, Information Protection. You’d need a global admin or “Compliance Administrator” or “Azure Information Protection Administrator” (?) role:

Since we are talking sensitivity labels for SharePoint Sites (not documents), we define label scope as “Groups and Sites”: “Configure privacy, access control, and other settings to protect labeled Teams, Microsoft 365 Groups, and SharePoint sites.”

Then we define which protection settings for groups and sites we should configure on the next steps:
– Privacy and external user access settings – Control the level of access that internal and external users will have to labeled teams and Microsoft 365 Groups.
– External sharing and conditional access settings – Control external sharing and configure Conditional Access settings to protect labeled SharePoint sites.

If we selected previously “Privacy and external user access settings” – now we need to select group/team privacy (These options apply to all Microsoft 365 Groups and teams, but not standalone sites). When applied, these settings will replace any existing privacy settings for the team or group. If the label is removed, users can change privacy settings again. You can also allow external user access – if group owner will be able to add guests:

Next step – define external sharing and conditional access settings. Specifically, if the content of the SharePoint site can be shared with Anyone (anonymously) or with authenticated users (new or existing) or no external sharing is allowed:

And you can either control the level of access users have from unmanaged devices or select an existing authentication context to enforce restrictions:

Configuring sensitivity labels policies
Sensitivity label policy is basically which label should be available to apply for what users and some other settings like
– do users need to provide justification before removing a label or replacing it with one that has a lower-order number or
– will users be required to apply labels and optionall the default label

View existing sensitivity labels
“Global reader” role allows view existing sensitivity labels configuration:

Wording would be a little different, but all aspects of the label configuration will be mentioned. E.g. when editing GUI says label scope is “Groups & sites”, read-only label summary defines Scope as “Site, UnifiedGroup”.
Gotchas
Applying sensitivity labels programmatically
To apply a label to a m365 group or Teams site with a group behind: MS Graph API support only Delegated permissions.
“Set-PnPSiteSensitivityLabel” works in the current site context.
Description says “If the site does not have a Microsoft 365 Group behind it, it will set the label on the SharePoint Online site and will not require Microsoft Graph permissions and will work with both delegate as well as app only logins.”
In fact (7/22/2022) app permissions are not working. This cmdlet can assign label to a standalone or a group-based site only with delegated permissions.
“Set-PnPTenantSite” allows you to remove or apply site sensitivity label to both standalone and group-based sites with app permissions. Furthermore, group and team settings respect this. I.e. if you apply label to a group-based site – group will pick this up.
References
Testing Sites.Selected SharePoint and MS Graph API
Sites.Selected MS Graph API permissions were introduced by Microsoft in March 2021. One year later, in 2022 they added SharePoint Sites.Selected API permissions.

Why is this so important? Because MS Graph API for SharePoint is still limited and cannot cover all possible needs. I’d estimate: 90% of applications use SharePoint CSOM, so developers have to use AppInv.aspx to provide permissions for their applications to SharePoint API.
But from this moment – having SharePoint API permissions in MS Graph – in theory – we can fully rely on permissions provided in Azure and – in theory – this should allow us disable SharePoint-Apps only principal:
Set-SPOTenant -DisableCustomAppAuthentication $true
My math professor taught me: “before trying to find a solution – ensure the solution exists.” So let us test:
Are we really able to work with a specific SharePoint site using MS Graph and SharePoint API Sites.Selected permissions provided via Microsoft Azure?
What will happen with our new/legacy applications if we disable SharePoint app-only SPNs (DisableCustomAppAuthentication)?
I’m getting controversial test results… maybe PnP.PowerShell 1.10 is not fully support SharePoint Sites.Selected API.
Tech Wizard (Sukhija Vikas) on March 20, 2022 in the article “SharePoint and Graph API APP only permissions for Selected Sites” suggests using pre-release (AllowPrerelease).
So please ignore the following for a while.
Meantime I’ll test providing SharePoint Sites.Selected API permissions via Graph API call.
(wip) Test set #1: Certificate vs Secret
DisableCustomAppAuthentication: $false (SP-app-only spns are enabled).
All applications have “write” access provided to a specific site only.
Connecting with Connect-PnPOnline and then test access with Get-PnPSite
App / Get-PnPSite | Secret | Certificate |
ACS based (Azure+AppInv) | OK | The remote server returned an error: (401) Unauthorized. |
MS Graph API Sites.Selected | The remote server returned an error: (403) Forbidden. | The remote server returned an error: (401) Unauthorized. |
SharePoint API Sites.Selected | OK | OK |
MS Graph API + SharePoint API Sites.Selected | Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) | OK |
App with no permissions | The remote server returned an error: (403) Forbidden | The remote server returned an error: (401) Unauthorized |
(wip) Test set #2: Sites.Selected SharePoint vs MS Graph (secret)
- DisableCustomAppAuthentication = $false
(SP-app-only spns are enabled). - All applications have “write” access provided to a specific site only.
- Using Client Secret (not a certificate)
- Using PnP.PowerShell
Action/Via | SharePoint + MS Graph Sites.Selected “secret” | SharePoint Sites.Selected “secret” | MS Graph Sites.Selected “secret” |
Connect-PnPOnline | WARNING: Connecting with Client Secret uses legacy authentication and provides limited functionality. We can for instance not execute requests towards the Microsoft Graph, which limits cmdlets related to Microsoft Teams, Microsoft Planner, Microsoft Flow and Microsoft 365 Groups. | WARNING: Connecting with Client Secret uses legacy authentication and provides limited functionality. We can for instance not execute requests towards the Microsoft Graph, which limits cmdlets related to Microsoft Teams, Microsoft Planner, Microsoft Flow and Microsoft 365 Groups. | WARNING: Connecting with Client Secret uses legacy authentication and provides limited functionality. We can for instance not execute requests towards the Microsoft Graph, which limits cmdlets related to Microsoft Teams, Microsoft Planner, Microsoft Flow and Microsoft 365 Groups. |
Get-PnPSite | OK | OK | The remote server returned an error: (403) Forbidden. |
Get-PnPList | OK | OK | |
Get-PnPListItem | OK | OK | |
Set-PnPSite | Attempted to perform an unauthorized operation. | ||
Set-PnPList | Attempted to perform an unauthorized operation. | ||
Set-PnPListItem | OK | OK | |
New-PnPList | Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) | ||
Add-PnPListItem | OK |
(wip) Test set #3: Read vs Write vs FullControl
DisableCustomAppAuthentication = $false
(SP-app-only spns are enabled).
All applications have Sites.Selected SharePoint and MS Graph API permissions.
Using Client Secret (not a certificate)
Using PnP.PowerShell
Read | Write | FullControl | |
Connect-PnPOnline | WARNING: Connecting with Client Secret uses legacy authentication and provides limited functionality. We can for instance not execute requests towards the Microsoft Graph, which limits cmdlets related to Microsoft Teams, Microsoft Planner, Microsoft Flow and Microsoft 365 Groups. | WARNING: Connecting with Client Secret uses legacy authentication and provides limited functionality. We can for instance not execute requests towards the Microsoft Graph, which limits cmdlets related to Microsoft Teams, Microsoft Planner, Microsoft Flow and Microsoft 365 Groups. | WARNING: Connecting with Client Secret uses legacy authentication and provides limited functionality. We can for instance not execute requests towards the Microsoft Graph, which limits cmdlets related to Microsoft Teams, Microsoft Planner, Microsoft Flow and Microsoft 365 Groups. |
Get-PnPSite | Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) | ||
Get-PnPList | Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) | ||
Get-PnPListItem | |||
Set-PnPSite | |||
Set-PnPList | |||
Set-PnPListItem | |||
New-PnPList | |||
Add-PnPListItem |
(wip) Test set #5: Certificate vs Secret
C#, SharePoint CSOM, PnP.Framework
Findings
PnP.PowerShell Get-, Grant-, Set- and Revoke-PnPAzureADAppSitePermission cmdlets require Azure App with MS Graph Sites.FullControl.All app permissions (otherwise it says “Access denied”) and authentication via certificate (otherwise it says “This cmdlet does not work with a ACS based connection towards SharePoint.”)
The same actions – managing permissions for the client app to the specific site collections – could be done via Microsoft Graph Sites Permissions API using just secret-based authentication.
If an azure app does not have Sites.Selected API permissions configured – “Grant-PnPAzureADAppSitePermission” works as expected – no error messages – the output is normal – as if Sites.Selected API permissions were configured in the app. The same for Get-, -Set and Revoke-. Permissions provided for the app to the site are not effective though: Connect-PnPOnline works well, but all other commands – starting from Get-PnPSite – returns “The remote server returned an error: (403) Forbidden.”
If an app have no permissions to SharePoint – “Connect-PnPOnline” works ok, but “Get-PnPSite” return an error: “The remote server returned an error: (403) Forbidden.”
Set-PnPAzureADAppSitePermission gives an error message “code”:”generalException”,”message”:”General exception while processing”
if the site is not specified.
AppInv is not working?
Error: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
References
- Track SharePoint App-only Service Principals in Microsoft 365
- Microsoft Graph Sites Permissions API
- “SharePoint and Graph API APP only permissions for Selected Sites”
Testing environment
- Microsoft 365 E5 Dev environment
- PowerShell 7.2.2
- PnP.PowerShell 1.10
- “write” permissions to the specific sites for client apps were assigned via PnP.PowerShell
Sites.Selected permissions to SharePoint Admin Site
WIP
What if we provide Sites.Selected App permissions to SharePoint Admin Site?
TBP