There are so many SharePoint code samples out there that it's really difficult to figure out what the current best way to do something is. Forgive me as I may very well be mixing technologies. Here's what I'm trying to figure out.
My environment:
- PowerShell v5.1 (Windows 10)
- Just downloaded SharePoint Online Management Shell yesterday, so it's the latest
- SharePoint Online with 2FA
- I am SharePoint Admin in the tenant
I'm seeing a lot of code samples for SharePoint Online that follow the same pattern. Get a "Context", then do the work. The 2 things I'm trying to do:
- I need to define an Add-only permission level like: https://sharepoint.stackexchange.com/a/212557
- I need to update the Created by field in all items in a list: https://www.sharepointdiary.com/2016/11/update-created-by-modified-by-created-at-modified-at-values-using-powershell.html
But the way they get the context doesn't work for me because in my case we have 2FA. So, code like this:
$SiteUrl = "https://XXXX.sharepoint.com/sites/XXXX/"
$Cred = Get-Credential
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
$Ctx.Credentials = $Credentials
$rootWeb = $Ctx.Web
$Ctx.Load($rootWeb)
$Ctx.ExecuteQuery()
Returns error: "The sign-in name or password does not match one in the Microsoft account system." Because it did not do 2FA.
So then I see other ways to "connect to SharePoint Online" with 2FA like this:
$orgName = "xxxx"
Connect-SPOService -Url https://$orgName-admin.sharepoint.com
Get-SPOSite
I then try creating a context after I've successfully connected using Connect-SPOService with 2FA, like this:
$SiteUrl = "https://xxxx.sharepoint.com/sites/xxxx/"
$orgName = "lgrb"
Connect-SPOService -Url https://$orgName-admin.sharepoint.com
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
$rootWeb = $Ctx.Web
$Ctx.Load($rootWeb)
$Ctx.ExecuteQuery()
But this fails with "The remote server returned an error: (403) Forbidden."
I just haven't been able to figure out how to marry the two. I.e. how do I get a working "Context" after I've established the connection via Connect-SPOService.
Thanks in advance!
Trying answer from SPM
Note: I was already able to successfully connect with Connect-SPOService before. The problem happens after with the ClientContext doing ExecuteQuery
I added the ClientContext code after the suggested code
I used $cred that was set up in the suggested code to pass to the context for Credentials
$orgName = "xxxx" $SiteUrl = "https://xxxx.sharepoint.com/sites/xxxx/" $userName = "xxxx" $passWord = "xxxx" $encPassWord = convertto-securestring -String $passWord -AsPlainText -Force $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $userName, $encPassWord Connect-SPOService -Url https://$orgName-admin.sharepoint.com $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl) $Ctx.Credentials = $cred $rootWeb = $Ctx.Web $Ctx.Load($rootWeb) $Ctx.ExecuteQuery()
However, the error is the same:
Exception calling "ExecuteQuery" with "0" argument(s): "The remote server returned an error: (403) Forbidden."
At line:13 char:1