Microsoft Graph PowerShell SDK Needs to Fix Its Password Problem
Graph SDK Plain Text Passwords are Unacceptable in Today’s Threat Climate

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.