Forum Discussion
EntilZha
May 07, 2021Iron Contributor
Resetting User’s Password using Microsoft Graph API
Working on a project to develop a tool and one aspect this tool is to rest a user’s password using Graph API with Application Permissions. Been searching on the internet and found a lot of suggestion...
- May 07, 2021Afaik application permissions are not supported for this operation.
EntilZha
May 17, 2021Iron Contributor
VasilMichev Again Thank You.....
Here's the function I use to get the Token.
Function HeaderToken-RW
{
# Define AppId, secret and scope, your tenant name and endpoint URL
$AppId = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
$AppSecret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
$Scope = "https://graph.microsoft.com/.default"
$TenantName = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
# Add System.Web for urlencode
Add-Type -AssemblyName System.Web
# Create body
$Body = @{
client_id = $AppId
client_secret = $AppSecret
scope = $Scope
grant_type = 'client_credentials'
}
# Splat the parameters for Invoke-Restmethod for cleaner code
$PostSplat = @{
ContentType = 'application/x-www-form-urlencoded'
Method = 'POST'
# Create string by joining bodylist with '&'
Body = $Body
Uri = $Url
}
# Request the token!
$Request = Invoke-RestMethod @PostSplat
# Create header
$Header = @{Authorization = "$($Request.token_type) $($Request.access_token)"}
Return $Header
}#End Header Function
Thank You,
-Larry
VasilMichev
May 18, 2021MVP
So you're still using application permissions (client secret), they are not supported for this endpoint.
- EntilZhaMay 20, 2021Iron ContributorThank You very much - had to make some adjustments but at least I'm getting the token and it's working. I tested on another endpoint because I was getting "Invoke-RestMethod : The remote server returned an error: (405) Method Not Allowed." on the password rest (passwordAuthenticationMethod) endpoint .
Now that I'm able to make it work, I'm able to take what you show me and expand on making more efficient.
Than You Very Much!!!!!!!
-Larry - VasilMichevMay 20, 2021MVPHere's a simple example that uses a username/password. Best work through the documentation and find the method that best works for you.
$req = Invoke-WebRequest -Method Post -Uri "https://login.microsoftonline.com/tenantname.onmicrosoft.com/oauth2/token" -Body "client_id=xxxxxxxxx-xxxx-xxxx-xxxx-da3ab8e46b00&grant_type=password&username=user@domain.com&password=P@ssw0rd123&scope=openid&resource=https://graph.microsoft.com" -Headers @{"Content-Type"="application/x-www-form-urlencoded"}
$token = ($req.Content | ConvertFrom-Json).access_token - EntilZhaMay 20, 2021Iron ContributorThank you Again and I believe that's the issue. After re-reading the Microsoft document that deals with passwordAuthenticationMethod: resetPassword, the authentication method is a Bearer {token}.
After reading through several site on how to construct a Bearer token using PowerShell, I'm still
Can you provide an basic example or point me to a good website that offer step by step instruction that will allow me to create Bearer Token using Credentials using PowerShell.
Thank You very much for the time your spending with me to get this to work.
-Larry - VasilMichevMay 20, 2021MVPThat sample is still using application permissions/client secret, it will not work. Update your HeaderToken function.
- EntilZhaMay 19, 2021Iron ContributorAgain thank You and I'm sorry for not grasping the concept, I still must be missing something.
Here is my script from start to finish.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Function HeaderToken
{
# Define AppId, secret and scope, your tenant name and endpoint URL
$AppId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
$AppSecret = 'xxxx.xxx.x..xxxx.x!!!!!111xxxxxx'
$Scope = "https://graph.microsoft.com/.default"
$TenantName = "XXXXXXXXXXXXXXXXXX.com"
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
# Add System.Web for urlencode
Add-Type -AssemblyName System.Web
# Create body
$Body = @{
client_id = $AppId
client_secret = $AppSecret
scope = $Scope
grant_type = 'client_credentials'}
$PostSplat = @{
ContentType = 'application/x-www-form-urlencoded'
Method = 'POST'
# Create string by joining bodylist with '&'
Body = $Body
Uri = $Url}
# Request the token!
$Request = Invoke-RestMethod @PostSplat
# Create header
$Header = @{Authorization = "$($Request.token_type) $($Request.access_token)"}
Return $Header
}#End Header Function
$authHeader = HeaderToken
$Body= @{
"newPassword" = "dkrRBW122"
}
$uri = "https://graph.microsoft.com/beta/users/xxxxx@xxxxxxxxx.com/authentication/passwordMethods/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx/resetPassword"
Invoke-WebRequest -Headers $authHeader -Uri $uri -Method Post -ErrorAction Stop -Body ($body | ConvertTo-Json -Depth 6)
#################### Error ###################
Getting the same error:
Invoke-WebRequest : The remote server returned an error: (403) Forbidden.
At C:\Users\jonesl\Desktop\Powershell Scripts\_BabylonProject\API-PWRest-Not Working.ps1:61 char:1
+ Invoke-WebRequest -Headers $Header -Uri $uri -Method Post -ErrorActio ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Thank You,
-Larry - VasilMichevMay 18, 2021MVPYou need to pass the token as part of the header. Also, you seem to be passing the user's GUID instead of the actual authentication method id. Here's a working example:
$body = @{
"newPassword" = "Parola123"
}
$uri = "https://graph.microsoft.com/beta/users/user@domain.com/authentication/passwordMethods/28c10230-6103-485e-b985-444c60001490/resetPassword"
Invoke-WebRequest -Headers $authHeader -Uri $uri -Method Post -ErrorAction Stop -Body ($body | ConvertTo-Json -Depth 6) - EntilZhaMay 18, 2021Iron Contributor
Again Thank you for responding!!!
Yes that is correct, using the application token did not work. Since I wasn't having any luck getting this API call to work i tried using -Header or -credential or both options.At the bottom of this messages is the function I tried using just credentials and this too failed with the following error.
Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.
At line:30 char:15
+ ... serResult = Invoke-RestMethod -Uri $PWResetURI -Method POST -Body $Bo ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExcepDo you have a recommendation on how I can get this to work?
Thank You,
-Larry
$Key = 'XXXXXXXXXXXXXX'
$AdminName = 'XXXXXXXXXX.com'
$EncryptPW = "XXXXXXXXXXXXXXXX"
$UserCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AdminName, ($EncryptPW | ConvertTo-SecureString -Key $Key)$UserAZGUID = 'XXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
$PWResetURI = "https://graph.microsoft.com/beta/users/$UserAZGUID/authentication/passwordMethods/$UserAZGUID/resetp..."
function Get-RandomCharacters($length, $characters)
{
$random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
$private:ofs=""
return [String]$characters[$random]
}$password = Get-RandomCharacters -length 2 -characters 'abcdefghiklmnoprstuvwxyz'
$password += Get-RandomCharacters -length 2 -characters 'ABCDEFGHKLMNOPRSTUVWXYZ'
$password += Get-RandomCharacters -length 3 -characters '1234567890'
$password += Get-RandomCharacters -length 2 -characters '!@&%(*'
Write-Host "[Line 304] Password randomly generated by script "$password -ForegroundColor Yellow$EncryptUserPW = ConvertTo-SecureString -String $Password -AsPlainText -Force
$Body = '{"newPassword" : "$EncryptUserPW"}'
$UserResult = Invoke-RestMethod -Uri $PWResetURI -Method POST -Body $Body -Credential $UserCredential -ContentType "application/json"