How do I store a MFA credential in Powershell

Aaron Martin picture Aaron Martin · Oct 10, 2018 · Viewed 7.7k times · Source

Under Basic authentication you used to be able to store credentials in a variable

$cred = Get-Credential

Now we are using Modern Auth and our Multi Factor Authentication is Duo.

How do I store my credentials for MFA into a variable so I can plug them into a script?

Example

$mfacred = *whateverthecodeis*
Connect-MsolService -Credential $mfacred
Connect-AzureAD -Credential $mfacred

Edit I do not want to bypass MFA, I want to prompt for it and store the credentials and token in such a way that the rest of the script can make use of the credentials and token.

Answer

Peter Kay picture Peter Kay · Oct 10, 2018

As far as my experience with MFA-enabled accounts within scripts. The only way you'll be able to bypass MFA is using cmdlets without the '-Credential' parameter.

The main use case for MFA is to protect against things like this: scripts running on a compromised account.

UPDATE:

So, there is a way to hack your way into programmatically getting the token. This is done by utilizing the ADAL binaries that come with the install of the Azure Modules and/or other O365 Modules. There is no easy way to prompt and store the token in a variable.

You will need to load the DLL in your script to start caching the token:

Add-Type -Path 'C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.x.x\Microsoft.IdentityModel.Clients.ActiveDirectory.dll'

You can acquire the access tokens beforehand by using the AcquireTokenAsync Method.

$accesstoken = [Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache]::DefaultShared
$accesstoken.ReadItems() | select DisplayableId, Authority, ClientId, Resource

The above ReadItem() method will give you all the information you need to store the token in a variable.

$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList #PLACE AUTHORITY URL HERE#
$client_id = "CLIENT_ID INFO"
$Credential = Get-Credential [email protected]
$AzureADCred = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential" -ArgumentList $Credential.UserName,$Credential.Password
$authResult = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authContext,"https://RESOURCE-URL.COM",$client_Id,$AzureADCred)

Once you have the token, you can use that to connect to your session, may it be exchange online, Azure, or Office.

$Authorization = "Bearer {0}" -f $authResult.Result.AccessToken
$Password = ConvertTo-SecureString -AsPlainText $Authorization -Force
$Ctoken = New-Object System.Management.Automation.PSCredential -ArgumentList "[email protected]", $Password

There is a caveat, these are only applying to the access tokens and does not take into account of refresh token. You might not even get the refresh token returned based on which ADAL binaries you use.

To learn more about access tokens, you can research more about it here