The use of multi-factor authentication (MFA) is growing by the day. More and more customers are enabling MFA for administrator accounts to protect their cloud environment a little bit more. But that also might affect your PowerShell scripts. In this post I want to point out how to deal with MFA enabled accounts in your PowerShell script.
Connecting to services
Before you can use cmdlets from modules like Azure PowerShell, Azure Active Directory and SharePoint Online you need to connect to these services first. Each of these services has its own “login” cmdlet. For example:
# Azure PowerShell Login-AzureRMAccount # Azure AD Connect-AzureAD # SharePoint Online Connect-SPOService -Url https://octavie365-admin.sharepoint.com
These cmdlets also have a parameter Credential and you can pass a PSCredential object. This is handy when you need to connect to multple services with the same credentials. One way to achieve this is to ask the username and password from the script.
$AdminUsername = Read-Host -Prompt "Azure/Office 365 Admin User Account" $AdminPassword = Read-Host -Prompt "Password" -AsSecureString $adminCredentials = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $AdminUsername, $AdminPassword Login-AzureRmAccount -Credential $adminCredentials Connect-AzureAD -Credential $adminCredentials
And of course, you can also use
$adminCredentials = Get-Credential
to get the Windows PowerShell login popup:
Windows Credential Manager
If you don’t way to ask for credentials in the script, you can also use the Windows Credential Manager. You need to install the module CredentialManager for this.
https://www.powershellgallery.com/packages/CredentialManager/2.0
( I am not going to describe how to set this all up. Plenty of articles available, such as https://www.petri.com/managing-usernames-passwords-powershell-sharepoint-online )
Once set up, your script can look like this:
# Get credentials from the Credential Manager $adminCredentials = Get-StoredCredentials -Target "MFADEMO" Login-AzureRmAccount -Credential $adminCredentials
What about MFA enabled accounts?
In spite of all the advanced scripting above, it simply does not work with MFA enabled accounts. You will see errors like this
Login-AzureRmAccount : AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access 'bla-bla'. Connect-SPOService : The sign-in name or password does not match one in the Microsoft account system.
The only solution available today (that I know of) is to use the cmdlets to connect to your service without the parameter Credential. This will show you the Sign in to your account popup of that service and this login window has the support for MFA. For example:
Does this mean you have to throw all your scripts into the recycle bin? No, you are going to accept and embrace this.
It is what it is.
You can add a switch parameter to your own script to indicate MFA should be used. With that you can have a if-then-else construction.
[CMDLetBinding()] Param( # Tenant Name [Parameter(Mandatory=$true,HelpMessage="Your tenant name. E.g. Mavention or Contoso")] [String] $TenantName, # Use MFA login [Switch]$MFA ) $urlSPOAdmin = "https://$($TenantName)-admin.sharepoint.com" if ( $MFA ) { Login-AzureRmAccount Connect-SPOService -Url $urlSPOAdmin } else { $AdminUsername = Read-Host -Prompt "Azure Admin User Account" $AdminPassword = Read-Host -Prompt "Password" -AsSecureString $adminCredentials = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $AdminUsername, $AdminPassword Login-AzureRmAccount -Credential $adminCredentials Connect-SPOService -Url $urlSPOAdmin -Credential $adminCredentials }
Summary
As more and more customers are enabling multi-factor authentication (MFA) for administrator accounts, your PowerShell scripts may not work anymore. In case of MFA enabled accounts, you have to use the cmdlets to connect to your service without the parameter Credential. The Sign-In window has support for MFA.
Thanks for the tips! I was running into this issue while running to run power shell scripts against an Office 365 tenant with MFA enabled. Leaving out the credential parameter and letting it prompt for authentication worked great.
Hi Sam,
Glad to hear!
grtz,
Octavie
I have a scheduled task (at night) executes a PS script that copies 400+ databases from prod to dev and creates a number of dev-specific accounts(AAD and Groups) and their permissions after the dev databases have copied. The copy step can be done with a non-AD account but the application of the dev-specific accounts must be done using an AAD account. MFA looks to break this template by requiring me to be there to provide and account and password information interactively. Am I missing something? Thanks for helping me see clearly.
Hi John,
Do I understand it correctly, that your daily scheduled script is running under the credentials (yours?) that has MFA enabled?
Looks to me that this should be better some service account without MFA enabled and having sufficient permissions (read: not necessarily the Global Admin role) to run this process.
grtz,
Octavie
Thanks for the reply and confirmation. The service account without MFA is the only approach that came to mind to address my situation.
Thanks for the information. However, I am not too sure about this statement
“Does this mean you have to throw all your scripts into the recycle bin? No, you are going to accept and embrace this.
It is what it is.”
Not to be blunt or anything, but embrace it and then what? We have Powershell scripts that run nightly to sync content to cloud. Basically, all of them have now become unusable because of MFA. Any insight into how those scripts can be enabled for MFA without user intervention?
Hi Michael, afaik you should not use an account with MFA for unattended processes like you describe. So, create and use a dedicated service account for your purpose and do not use MFA.
Cheers,
Octavie
This script sort of can be added to your scripts to solve the issue, only thing now is you gotta update from Login-AzureRm to Az, which has a fancy migration tool for it from microsoft. Cheers!
You could make a script that uses access and refresh tokens, you would only have to authenticate once (with mfa).