From the Operating Room: PowerShell for SPO with MFA
CSOM with SharePointOnline sites using Multi-Factor-Authentication in 2019
In 2019, interacting with SharePoint Online is different than it has been, but also much the same.
- Multi-Factor-Authentication (MFA) is becoming the standard.
- New methods are being released.
- Old methods still work, and these methods are the most well documented.
- New methods can be use with old ones, its just not always obvious what the differences are, results can be unexpected, and new method documentation gets lost in the old.
- Something New Tomorrow!
For this discussion, Multi-Factor-Authentication will be examined: Updaing older methods of connecting with new methods and making the rest of the script work like it always has.
Connecting to SPO:
- Grab a Cred
- Set up a query
- Bingo-Bango - connected - run your script.
- Open Web Login Form and Authenticate
- Set up a query
- Bingo-Bango - connected - run your script
Although.... When I first tried to make MFA work, there was no immediate Bingo-Bango moment....
This was a script that works in other (Non-MFA) SharePointOnline sites. It needed to be updated for a client who preferred to not dumb-down an account by removing MFA, just to run a script. Reasonable request.
Searching for clues to implementing, I ran across a plethora of old methods for connecting via MFA - they were all terrible. I found the updated SharePoint-PnP Powershell library (https://github.com/SharePoint/PnP-PowerShell). Aftr some initial tinkering, I could get the web login to show and all that, but the rest of my script no longer worked. The connection method, using the commandlets, instead of straight CSOM, presented an issue of Context. It took too long, but I did fing the commandlet that allowed the script to (kind of) start working again.
This 'normal login':
#Setup Credentials to connect
$Cred = Get-Credential
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
#Login is not actually performed until operations are made against the Context - see below #Setup the contexts
Became this 'MFA login':
Connect-PnPOnline -Url $SourceSiteURL -UseWebLogin
After connecting, I needed a valid Context; originally:
#Setup the contexts
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SourceSiteURL)
$ctx.Credentials = $Credentials
After changing to connect via MFA:
After getting a proper Context for my MFA connection, I was able to login where I hit another brick wall:
For some reason, the objects references after this change were slightly different. I got an error complaining that a function paramaeter could not convert a:
No warm and fuzzies from that one... I ended up restructuring the script to something a little bit simpler, then had to change all of the Folder.Name property references to Folder.Title, and all was (basically) well.
The mixed methods work. The mix of old and new is a bit ugly. There are new ways to do everything that the old script is doing, and should probably be updated to match. But... then there's the old addage, if it ain't broke... (and I have 'better' (read: paid) things I can be working on)
Questsions? Please send your questions or make an appointment today for a consult via email to firstname.lastname@example.org