Forum Discussion
PowerShell Script to Follow a SharePoint Site for a User
Good morning!
I've been struggling with this for a while now. I've tried multiple scripts that are supposed to do this and run into many errors. I have a new script I found, which seems to mostly work, but it gives me this one error:
Write-Error: Response status code does not indicate success: Forbidden (Forbidden).
It looks like a permissions issue. I'm executing this in VSC, running under my user account, but when it connects to Graph, I'm authenticating it as my admin account, which has the following roles:
I do realize how easy it is for users to follow a site, but this is one of those messed-up political situations, so I need a way to do this.
After the error, it just hangs here:
Add users to follow site(. [Adding user 'Ken Ce.]
Here is the script I'm using:
# Example: .\Add-FollowUserSite.ps1 -UsersMail "user1@[domain].com","user2@[domain].com","user3@[domain].com" -SitesUrl "https://[domain].sharepoint.com"
[CmdletBinding()]
param(
[Parameter(Mandatory=$true,HelpMessage="List of Users Mails")]
[String[]]$UsersMail=@("user1@[domain].com","user2@[domain].com","user3@[domain].com"),
[Parameter(Mandatory=$true,HelpMessage="List of SharePoint Url to follow")]
[String[]]$SitesUrl=@("https://[domain].sharepoint.com")
)
Begin{
# Validate Modules ffor Microsoft graph users exist
if (Get-Module -ListAvailable -Name microsoft.graph.users) {
Write-Host "Microsoft Graph Users Module Already Installed"
}
else {
try {
Install-Module -Name microsoft.graph.users -Scope CurrentUser -Repository PSGallery -Force -AllowClobber
}
catch [Exception] {
$_.message
}
}
# Validate Modules ffor Microsoft graph users exist
if (Get-Module -ListAvailable -Name microsoft.graph.sites) {
Write-Host "Microsoft Graph Sites Module Already Installed"
}
else {
try {
Install-Module -Name microsoft.graph.sites -Scope CurrentUser -Repository PSGallery -Force -AllowClobber
}
catch [Exception] {
$_.message
}
}
# Import Modules Microsoft.Graph.users and Microsoft.Graph.sites to be used
Import-Module Microsoft.Graph.users
Import-Module Microsoft.Graph.sites
Write-Host "Connecting to Tenant" -f Yellow
Connect-MgGraph -Scopes "Sites.ReadWrite.All", "User.Read.All"
Write-Host "Connection Successful!" -f Green
}
Process{
$count = 0
$UsersMail | foreach {
#Get user Graph properties
$mail = $_
$user = Get-MgUser -ConsistencyLevel eventual -Count 1 -Search ([string]::Format('"Mail:{0}"',$mail))
$SitesUrl | foreach {
#Get Site Graph properties
$domain = ([System.Uri]$_).Host
$AbsolutePath = ([System.Uri]$_).AbsolutePath
$uriSite = [string]::Format('https://graph.microsoft.com/v1.0/sites/{0}:{1}',$domain,$AbsolutePath)
$site = Invoke-MgGraphRequest -Method GET $uriSite
#Create Body for Post request
$body = @'
{
"value": [
{
"id": "{$SiteID}"
}
]
}
'@.Replace('{$SiteID}',$site.id)
#Graph call that include user to follow site
$uriFollow = [string]::Format('https://graph.microsoft.com/v1.0/users/{0}/followedSites/add',$user.Id)
#Include follow option from user to SharePoint Site
try{
$response = Invoke-MgGraphRequest -Method POST $uriFollow -Body $body -ContentType "application/json"
Write-Host "User '$($user.DisplayName)' is following site '$($AbsolutePath)'" -f Green
}
catch {
Write-Error $_.Exception
}
}
$count += 1
#progress bar
Write-Progress -Activity 'Add users to follow site(s)' -Status "Adding user '$($user.DisplayName)' to follow sites... ($($count)/$($UsersMail.Count))" -PercentComplete (($count / $UsersMail.Count) * 100)
}
}
End {
Disconnect-MgGraph
Write-Host "Finished" -ForegroundColor Green
}
Any help would be greatly appreciated.
4 Replies
- Andres-BohrenSteel Contributor
Hi kcelmer
I did play around a little bit with Interactive Permissions (like in your example).
I was not able to add or remove a Follower (other than my own user)############################################################################### # Connect with MgGraph Interactive ############################################################################### Connect-MgGraph -Scopes "Sites.ReadWrite.All","User.Read.All" -NoWelcome #Get User $UPN = "email address removed for privacy reasons" $User = Get-MgUser -UserId $UPN Write-Host "UserID: $($user.id)" -ForegroundColor Cyan #Details of SharePoint Site $SiteURL = "https://icewolfch.sharepoint.com/sites/DemoPrivate" $Domain = ([System.Uri]$SiteURL).Host Write-Host "Domain: $Domain" -ForegroundColor Cyan $AbsolutePath = ([System.Uri]$SiteURL).AbsolutePath.split("/")[2] Write-Host "$AbsolutePath" -ForegroundColor Cyan $uriSite = [string]::Format('https://graph.microsoft.com/v1.0/sites/{0}:{1}',$Domain,$AbsolutePath) $Site = Invoke-MgGraphRequest -Method GET $uriSite Write-Host "SiteID: $($site.id)" -ForegroundColor Cyan #Create Body for Add/Remove $params = @{ value = @( @{ id = $Site.ID } ) } #Create Body for Add/Remove $params = @{ value = @( @{ id = $Site.ID } ) } #Add Follower Write-Host "Add Follower to Site: $($Site.Id)" -ForegroundColor Cyan Add-MgUserFollowedSite -UserId $user.Id -BodyParameter $params #Remove Follower Write-Host "Remove Follower to Site: $($Site.Id)" -ForegroundColor Cyan Remove-MgUserFollowedSite -UserId $user.Id -BodyParameter $params
Tried with an Entra App and Certificate for Authentication.
Be aware that List followed sites is not Supported with Application Permissions
https://learn.microsoft.com/en-us/graph/api/sites-list-followed?view=graph-rest-1.0&tabs=http
############################################################################### # Connect with Entra Application ############################################################################### # Application Permissions # - Sites.ReadWrite.All # - User.ReadBasic.All ############################################################################### $AppID = "2f79c9c9-4024-4d46-a06f-67c1f2d92b02" $TenantID = "icewolfch.onmicrosoft.com" $CertThumbprint = "A3A07A3C2C109303CCCB011B10141A020C8AFDA3" Connect-MgGraph -AppId $AppID -TenantId $TenantID -CertificateThumbprint $CertThumbprint -NoWelcome #Get User $UPN = "email address removed for privacy reasons" $User = Get-MgUser -UserId $UPN Write-Host "UserID: $($user.id)" -ForegroundColor Cyan #Details of SharePoint Site $SiteURL = "https://icewolfch.sharepoint.com/sites/DemoPrivate" $Domain = ([System.Uri]$SiteURL).Host Write-Host "Domain: $Domain" -ForegroundColor Cyan $AbsolutePath = ([System.Uri]$SiteURL).AbsolutePath.split("/")[2] Write-Host "$AbsolutePath" -ForegroundColor Cyan $uriSite = [string]::Format('https://graph.microsoft.com/v1.0/sites/{0}:{1}',$Domain,$AbsolutePath) $Site = Invoke-MgGraphRequest -Method GET $uriSite Write-Host "SiteID: $($site.id)" -ForegroundColor Cyan #Create Body for Add/Remove $params = @{ value = @( @{ id = $Site.ID } ) } #Add Follower Write-Host "Add Follower to Site: $($Site.Id)" -ForegroundColor Cyan Add-MgUserFollowedSite -UserId $user.Id -BodyParameter $params #Remove Follower Write-Host "Remove Follower to Site: $($Site.Id)" -ForegroundColor Cyan Remove-MgUserFollowedSite -UserId $user.Id -BodyParameter $params
Hope that helps.
Kind RegardsAndres
- kcelmerBrass Contributor
Thank you Andres! It looks like you put considerable effort into this. Just to clarify, were you able to follow a site for a user with the Entra/certificate approach?
- Andres-BohrenSteel Contributor
Hi kcelmer
I found an error in the codeThe Graph Endpoint sites only returns the "Team site (classic experience)"
https://graph.microsoft.com/v1.0/sites/<tenant>.sharepoint.com
If you use the following command you get the Websites with the ID's
Get-MgSite | where {$_.DisplayName -match "demo"} Get-MgSite | where {$_.DisplayName -eq "IcewolfDemo"}
############################################################################### # Connect with Entra Application ############################################################################### # Application Permissions # - Sites.ReadWrite.All # - User.ReadBasic.All ############################################################################### $AppID = "2f79c9c9-4024-4d46-a06f-67c1f2d92b02" $TenantID = "icewolfch.onmicrosoft.com" $CertThumbprint = "A3A07A3C2C109303CCCB011B10141A020C8AFDA3" Connect-MgGraph -AppId $AppID -TenantId $TenantID -CertificateThumbprint $CertThumbprint -NoWelcome #Get User $UPN = "email address removed for privacy reasons" $User = Get-MgUser -UserId $UPN Write-Host "UserID: $($user.id)" -ForegroundColor Cyan $SiteID = "icewolfch.sharepoint.com,e5167e43-7495-4611-b74c-bbf2ffd85ce5,0c772746-d2d9-4c13-8176-bd41df1b7a6e" #IcewolfDemo #Create Body for Add/Remove $params = @{ value = @( @{ id = $SiteID } ) } #Add Follower Write-Host "Add Follower to Site: $($Site.Id)" -ForegroundColor Cyan Add-MgUserFollowedSite -UserId $user.Id -BodyParameter $params #Remove Follower #Write-Host "Remove Follower to Site: $($Site.Id)" -ForegroundColor Cyan #Remove-MgUserFollowedSite -UserId $user.Id -BodyParameter $params
The Graph Query on the User is updated
https://graph.microsoft.com/v1.0/users/<userprincipalname>/followedSitesAnd the Followed Sites in SharePoint is reflecting that (takes a few Minutes until that's visible here)
So yes, it works but you have to figure out the SiteID and use that as a Parameter.
Kind Regards
Andres