Microsoft Graph PowerShell SDK Needs to Fix Its Password Problem

Graph SDK Plain Text Passwords are Unacceptable in Today’s Threat Climate

Graph SDK plain text passwords problem

Many PowerShell developers are all too aware that time is running out for the Azure AD and MSOL modules. Microsoft will retire the MSOL module in April 2025 and the Azure AD module in Q3 2025. The result is that a lot of work is going on to upgrade scripts to replace MSOL and Azure AD cmdlets with equivalents from the Microsoft Graph PowerShell SDK or Entra module.

Microsoft launched the Entra module in June 2024 and made its V1.0 release generally available in January 2025. The Entra module is built on top of the Microsoft Graph PowerShell SDK. The major difference is that the Entra module comes with a set of hand-crafted cmdlets intended to mimic how Azure AD cmdlets work. I say hand-crafted because Microsoft engineers upgrade the automatically-generated versions created for the SDK to add support for features like piping.

The AutoRest process, which generates the SDK cmdlets, uses the metadata of the underlying Graph APIs to guide what it generates. That metadata is not constructed with PowerShell in mind, which is why the SDK cmdlets can be difficult to work with at times. For instance, the SDK cmdlets don’t support piping, which is a fundamental PowerShell feature. Output from SDK cmdlets is often a set of identifiers rather than human-understandable objects, and so on.

You could ask why Microsoft doesn’t intervene to add support for piping, make cmdlet output more useful, and address the other SDK foibles. One reason is the sheer number of Graph APIs that end up as SDK cmdlets.

[array]$Command = Get-Command -Module Microsoft.Graph*
$Command.count
42474

The 42,474 cmdlets are broken down into 15,259 V1.0 and 27,215 beta cmdlets. Updating all the cmdlets in V2.25 of the Microsoft Graph PowerShell SDK would take enormous effort. The number of cmdlets grows with each version of the SDK to reflect newly-added Graph APIs. The automatic generation process would need to change (and testing of the generated cmdlets). Whether the world’s largest software company should do this is an argument that’s been going on for years.

All of which brings me to issue 3119 reported in the SDK’s GitHub repository reported by MVP Aleksandar Nikolić, a well-known PowerShell expert. The problem report is terse and accurate:

The Update-MgUserPassword command’s parameters, -CurrentPassword and -NewPassword, expect a string value instead of a SecureString value.

Using Graph SDK Plain Text Passwords to Update User Accounts

The Update-MgUserPassword cmdlet is designed to allow users to change their own password. For instance, this code updates the user who’s signed into an SDK interactive session.

$User = Get-MgUser -UserId (Get-MgContext).Account

Update-MgUserPassword -UserId $User.Id -NewPassword "P@sswOrD" -CurrentPassword "Galway2020!!!"

If an administrator is changing someone’s password, they should use the Update-MgUser cmdlet.

$NewPasswordProfile = @{}
$NewPasswordProfile["Password"]= "$!FDGmso13@"

Update-MgUser -UserId $User.Id -PasswordProfile $NewPassword

Notice that in both cases, the password is in clear text. I don’t know how many tenants have coded solutions to allow users to change their own passwords and use the Update-MgUserPassword cmdlet, but I know that many have processes to change user passwords with Update-MgUser, so that’s the more serious problem.

By comparison, the equivalent cmdlets from the now-deprecated modules both take SecureString values when changing passwords.

$NewPassword | ConvertTo-SecureString -AsPlainText -Force
Set-MsolUserPassword -UserPrincipalName $userPrincipalName -NewPassword $NewPassword -ForceChangePassword $true
Set-AzureADUserPassword -ObjectId $User.Id" -Password $NewPassword

Using Secure Strings for Password Changes

Microsoft defines a SecureString as “text that should be kept confidential.” In terms of security, Microsoft says that A SecureString “provides more data protection than a string.” It seems like the right kind of protection passwords should have.

You might consider that there’s nothing much wrong here because the passwords are available to those who set them. However, it’s possible to have a script generate a password for an account and store it as a SecureString in a repository like Azure Key Vault, and have a different script read the password and use it to update an account. This method means that no password ever appears in plain text.

The Solution to Graph SDK Plain Text Passwords

The initial response from the SDK development team was that they follow the documentation for the underlying user: ChangePassword Graph API, which defines the input values in the request body strings. Referring back to the Graph API seems like a dereliction of duty. If everyone did that, we’d never see any improvements in software. Switching to support SecureString input for the SDK cmdlets is the right thing to do, even if it might break some existing scripts. That’s an acceptable cost to pay for better security.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

One Reply to “Microsoft Graph PowerShell SDK Needs to Fix Its Password Problem”

  1. It’s always someone else’s fault with those guys, never the SDK. God forbid they actually spend some time producing cmdlets that conform to PowerShell standards. Or maybe they should talk to the marketing people, as apparently Copilot is the solution for everything 😛
    I stopped reporting issues long ago. Hoping the Entra module will eventually provide some relief, even though its scope is limited.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.