Sweet mother Mary, I got it! It was the content type. I was using application/json
and it wanted application/x-ww-form-urlencoded
This code works properly to set the password for a user:
function Set-ProGetUserPassword {
[Cmdletbinding()]
Param(
[Parameter(Mandatory)]
[String]
$Username,
[Parameter(Mandatory)]
[SecureString]
$OldPassword,
[Parameter(Mandatory)]
[SecureString]
$NewPassword
)
begin {
$confirm = Read-Host "Please re-enter your new password" -AsSecureString
$identical = Compare-SecureString -SecureString1 $NewPassword -SecureString2 $confirm
if (-not $identical) {
Write-Error 'Passwords do not match!'
break
}
}
end {
$unmanagedString = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewPassword)
$plainTextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($unmanagedString)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($unmanagedString) # Clean up
$iterations = 10000
$saltLength = 10
$hashLength = 20
$rfc2898 = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($plainTextPassword, $saltLength, $iterations)
$passwordBytes = $rfc2898.GetBytes($hashLength)
$saltBytes = $rfc2898.Salt
$base64Password = [System.Convert]::ToBase64String($passwordBytes)
$base64Salt = [System.Convert]::ToBase64String($saltBytes)
$body = @{
User_Name = $Username
Password_Bytes = $base64Password
Salt_Bytes = $base64Salt
}
Write-Verbose $body
$Params = @{
Slug = '/api/json/Users_SetPassword'
Method = 'POST'
Body = $body
ContentType = 'application/x-www-form-urlencoded'
}
Invoke-ProGet @Params
}
}