I have an Azure App Registration setup as below:
Not shown: two redirect URIs for https://login.microsoftonline.com/common/oauth2/nativeclient (which I believe is needed for auth code flows if using PowerShell?) and https://MYDEVSERVER
We have a web API that can correctly access Graph against this App Registration by using a hybrid on-behalf-of flow and IConfidentialClientApplication, along with a bootstrap token provided by an Office add-in.
The creation of this App Registration is actually done by a PowerShell script, and I want to add a feature that will try to login as the script user to make a test Graph API call (against the /me endpoint) to make sure it is setup correctly. The script can ensure that the App Registration is granted admin consent for the Graph API permissions so the script user does not have to provide consent.
From what I understand, the authorization code flow can be used to test these delegated permissions. However, I've tried two approaches with different results as below using the MSAL module to get the token and then use that token in the authorization header for a Graph call to simply return details about the logged in user via the /me endpoint:
If I don't pass a client secret to the Get-MsalToken cmdlet, I do get a login prompt but Get-MsalToken always returns the error 'AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'
If I do provide a client_secret, I do NOT get the login prompt and can successfully get a token, but the Graph call fails saying that the /me request is only valid with delegated authentication flow. Which makes sense because we need a user context.
So I'm stuck - I can't use the user context with the interactive login without it expecting a client secret that if I do use is using a different flow that's not supporting delegated permissions. What am I doing wrong? Or do I need to use a completely different authentication flow?
Does the fact that the App Registration is designed to handle SSO with Office web add-ins have anything to do with it? Meaning, I have a scope (e.g. api://MYWEBSERVER/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/access_as_user, as used by the add-in manifests for purposes of issuing a bootstrap token from the Office JS library to our Web API) and a list of authorized client applications (Office apps) in the 'Expose an API' section. I'm wondering if only those applications are authorized, and not the PowerShell script...
I've also seen some suggestions about using the device code flow and I'm wondering if I'm missing a step to get a refresh token (as demonstrated here but I can't get that example to work either using a client secret (I can't figure out the proper Get-MsalToken parameter combination).
$graphEndPointUrl = "https://graph.microsoft.com/v1.0/me"
$connectionDetails = #{
'TenantId' = $tenantId #Set variable to your own value
'ClientId' = $clientId #Set variable to your own value
'Scopes' = 'https://graph.microsoft.com/.default'
}
#Using the above information, it throws this error on Invoke-RestMethod:
#ERROR: "{"error":"invalid_client","error_description":"AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.
#"error_codes":[7000218]
#"error_uri":"https://login.microsoftonline.com/error?code=7000218"}"
$connectionDetails = #{
'TenantId' = $tenantId #Set variable to your own value
'ClientId' = $clientId #Set variable to your own value
'ClientSecret' = $clientSecret | ConvertTo-SecureString -AsPlainText -Force #Set $clientSecret variable to your own value
'Scopes' = 'https://graph.microsoft.com/.default'
}
#Using the above information, it throws this error on Invoke-RestMethod:
#ERROR: "{"error":{"code":"BadRequest","message":"/me request is only valid with delegated authentication flow."
Import-Module MSAL.PS
try {
$myAccessToken = Get-MsalToken #connectionDetails
Write-Host $myAccessToken.AccessToken
$authHeader = #{
'Authorization' = $myAccessToken.CreateAuthorizationHeader()
}
$response = Invoke-RestMethod -Uri $graphEndPointUrl -Headers $authHeader
#Error thrown below
if ($null -eq $response) {
Write-Error "An unexpected error occurred making a test Graph API call to the $($graphEndPointUrl) endpoint" -ForegroundColor Red
}
else {
Write-Host "The test Graph API call to the $($graphEndPointUrl) endpoint was successful!"
}
}
catch {
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$responseBody = $reader.ReadToEnd();
$errorObj = ConvertFrom-Json -InputObject $responseBody
Write-Host "An unexpected error occurred making a test Graph API call to the $($graphEndPointUrl) endpoint: $($errorObj.error.message)"
}
Update
Everything you need I believe is written in this Microsoft article - https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
I noticed a key difference in the tutorial you referenced and your setup, thats the ID Token that is used with the hybrid setup, you can read more about it in the MS guide, check response_mode .
So principal goes as follow > You get an authorization code > use that code to generate your access and refresh tokens > then you can use different API calls with the Access token in the header.
As for your code, here are the things that are missing or are not correctly implemented.
You are missing the RedirectUri param. Make sure the URL is exact I have just put https://localhost as an example.
$connectionDetails = #{
'TenantId' = $tenantId #Set variable to your own value
'ClientId' = $clientId #Set variable to your own value
'ClientSecret' = $clientSecret | ConvertTo-SecureString -AsPlainText -Force #Set $clientSecret variable to your own value
'Scopes' = 'https://graph.microsoft.com/.default'
'RedirectUri' = 'https://localhost'
}
Your header is not implementing the Authorization properly. Check out the example from the tutorial
$myAuthMethods = (Invoke-RestMethod -Headers #{Authorization = "Bearer $($myAccessToken.AccessToken)" } `
-Uri "https://graph.microsoft.com/beta/me/authentication/methods" `
-Method Get).value
$myAuthMethods
The header have the following structure, where the word Bearer is before the token.
$header = #{
"Authorization" = "Bearer $($myAccessToken.AccessToken)"
}
Make sure you have the access token $myAccessToken.AccessToken in the header.
At that point, you should at least get a different error if request does not proceed.
The issue is that an additional "Mobile and desktop applications" platform needs to be added to the App Registration on the Authentication page (with "https://login.microsoftonline.com/common/oauth2/nativeclient" as a Redirect URI), as it only has a web platform currently. Then Get-MsalToken works without a client Id:
$myAccessToken = Get-MsalToken -ClientId $clientID -TenantId $tenantId -Interactive -Scopes 'https://graph.microsoft.com/.default' -RedirectUri 'https://login.microsoftonline.com/common/oauth2/nativeclient'
However, an additional request is needed to get a refresh token and use that for the Graph call:
$myAccessToken = Get-MsalToken -ClientId $clientID -TenantId $tenantId -Silent
Related
Running the following Powershell command
$tokenresponse = Get-MsalToken -ClientId $clientID -TenantId $tenantID -Interactive -RedirectUri "http://localhost"
gives me the error:
AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.
All solutions I found are pointing to the direction, that in the Azure Protal I should enable "Allow public client flows" but this setting is enabled. Any idea how I can get the token (I would need to get a token for delegated permissions)
I know this is an old question, but my answer below might help someone in the future. I ran into this same problem today and the way to fix it was by correcting the configuration on the App Registration. The solution was quite simple. I just had to set up Authentication to the right platform: "Mobile and desktop applications". Instead of Web or SPA.
To test it, get your tenant id and application (client) id, and pass it to the Get-MsalToken commandlet like below. The login page should pop-up, including any MFA dialogs (if MFA is configured).
$tenant_id = "00000000-0000-0000-0000-0000000000000"
$client_id = "00000000-0000-0000-0000-0000000000000"
$authParams = #{
ClientId = $client_id
TenantId = $tenant_id
Interactive = $true
}
$auth = Get-MsalToken #authParams
$auth
I am building a script with a colleague. This script will show a popup.
We want this popup only to be shown to a certain group of users (teachers and not students). So we want to check group membership of a user. Since this script will be installed on the computer locally and we would not like to install azuread cmdlets on all our computers and also not pass azure ad credentials to the script.
So we where wondering if their is azure-ad info about group membership stored on the computers locally. And also if we can acces it via powershell? (if we could get jobtitle of user that would also be helpfull)
Other ideas are also welcome.
The information related user that you are looking for less likely to be stored locally.
So to meet your requirement, you will have to have some means to communicate with the Azure AD. Your requirement was not to make use of any additional libraries and by using PowerShell.
Graph API can come handy.
To prevent user intervention, you can use App only Graph permission for the App.
You can refer this article to know more App registration, client secret & Application permission :
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
https://learn.microsoft.com/en-us/graph/notifications-integration-app-registration
You consume the graph endpoint from PowerShell and acquire the necessary details of the logged user from the Azure AD without a necessity of external libraries.
#Acquiring the graph token
$web="https://login.microsoftonline.com/<TENANT ID>/oauth2/v2.0/token"
$body = "client_id=<CLIENT ID>&scope=https://graph.microsoft.com/.default&client_secret=<CLIENTSECRET>&grant_type=client_credentials"
$response = Invoke-WebRequest $web -Body $body -Method Post
$token = ($response | ConvertFrom-Json).access_token
#Getting the logged username that will be used in the graph api
$upn = $env:USERNAME + "#" + $env:USERDNSDOMAIN
#building the authorization header
$header = #{"Authorization" = " Bearer $token"}
#gettting the user details
$content = Invoke-WebRequest "https://graph.microsoft.com/v1.0/users/$upn" -Headers $header -Method Get
$details = $content.Content | ConvertFrom-Json
#getting the group membership
$content = Invoke-WebRequest "https://graph.microsoft.com/v1.0/users/$upn/memberof" -Headers $header -Method Get
$groupdetails = ($content.Content | ConvertFrom-Json).value
Working scenario
I have an Azure web application (https://www.contoso.com) to which I want to authenticate against and perform web call on.
I want to authenticate myself using Connect-AzAccount and make calls to it using my own identity.
I use the following code with success to obtain a valid token and call the application.
#Authenticate as myself or a sevice principal
Connect-AzAccount -Tenant 'a736bac3-c259-450f-90a4-f7d5bd7c4c78'
# App registration ID for Contoso
$ResourceUri = '24114488-8c26-4e87-8f71-90de62f5a8aa'
$Context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $ResourceUri).AccessToken
$Headers = #{Headers = #{Authorization = "Bearer $token" } }
Invoke-RestMethod -Method Get -uri 'https://Contoso.com/module/Something' #Headers
That being said, the application itself does not implement forced user & groups assignment.
Instead, everybody can connect to it (by design).
The problematic
The solution presented above requires me to add Powershell Azure (1950a258-227b-4e31-a9cf-717495945fc2) in the list of Authorized client application to enable this scenario. By doing this operation, anybody in my directory can now technically make calls to the website, which is not desired.
Desired Scenario
Because user assignment is not enforced, I removed the Powershell Azure client from the main app and instead created a second App Registration for which I authorized the PS AZ client and added an API permission so it had access to the main App. The idea is that I can require user assignement for the second app registration and therefore limit the user that can make these kind of calls.
Initial (working) flow:
Connect-AzAccount authenticate the user
Code sample above is ran to obtain the token and call the app.
Desired flow
Connect-AzAccount authenticate the user
User connect through the client app registraion (new app) that has api permission to the main app.
User make calls to the main app.
Now, if I try to use my initial code sample with the Application Id of the second registration acting as a client ID, I get the following error
Invoke-RestMethod : {"code":401,"message":"IDX10214: Audience validation failed. Audiences: '[PII is hidden]'. Did not
match: validationParameters.ValidAudience: '[PII is hidden]' or validationParameters.ValidAudiences: '[PII is hidden]'."}
At line:1 char:12
+ $result2 = Invoke-RestMethod -Method Get -uri 'https://Contoso.com/so...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExcept
ion
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I believe that this is because I am obtaining a token for the second app registration and trying to call the main app URL, which is not authorized through the token.
A "working" alternative to this problem would be to connect using Client_credentials as grant_type such as this:
function get-Bearer([string]$TenantID, [string]$ClientID, [string]$ClientSecret) {
$TokenEndpoint = "https://login.windows.net/{0}/oauth2/token" -f $TenantID
$Body = #{
'resource' = '24114488-8c26-4e87-8f71-90de62f5a8aa'
'client_id' = $ClientID
'grant_type' = 'client_credentials'
'client_secret' = $ClientSecret
}
$params = #{
ContentType = 'application/x-www-form-urlencoded'
Headers = #{'accept' = 'application/json' }
Body = $Body
Method = 'Post'
URI = $TokenEndpoint
}
$token = Invoke-RestMethod #params
Return "Bearer " + ($token.access_token).ToString()
}
If I do that, even though I can make calls to the main app. again but it is connected with the actual client app. and not using the user identity obtained through Connect-AzAccount (for which tokens can be generated through the initial sample)
I was also able to make it work with a password grant_type but this is not making use of my bearer token and is also invalidated by MFA enabled users.
All insights are welcome.
References
Microsoft Identity platform documentation - v2-oauth2-on-behalf-of-flow
(digging around the application flow to try and get something working)
Application app ids, not object ids, should be used as resources identifiers. Keep getting tokens using the first application (24114488-8c26-4e87-8f71-90de62f5a8aa) as resource/audience (using its application id uri) and the second application as client. Connect-Az will be out of the equation.
#Install the ADAL.PS package if it's not installed.
if(!(Get-Package adal.ps)) { Install-Package -Name adal.ps }
$authority = "https://login.windows.net/common/oauth2/authorize"
#this is the security and compliance center endpoint
$resourceUrl = "{first application id uri}"
#replace <redirect-uri>, with the Redirect URI from your Azure AD application registration.
$clientId = "{second application app id}"
$redirectUri = "<redirect-uri>"
$response = Get-ADALToken -Resource $resourceUrl -ClientId $clientId -RedirectUri $redirectUri -Authority $authority -PromptBehavior:Always
$response.AccessToken | clip
I finally succeeded in my attempt.
In case my initial question was confusing, I "simply" wanted to connect as myself on Web API B using an intermediary Web API A
The reason was that I could not implement control access on Web API B (it is a requirement that it is available for all users of the tenant) and I also could not add Powershell client ID to Web API B directly as this would have allowed everyone to obtain a token and make call to Web API B using Powershell.
Therefore, I needed the intermediary Web API A to allow Powershell client ID and provide a controlled / limited user access to Web API B
There is a flow in the Microsoft identity platform and Oauth 2.0 called On-Behal-Of flow which allow exactly that scenario.
Prerequisites
App Registration for Web API B
API Permission: Delegated permission to User.Read (Graph API)
Expose an API: add a User_Impersonation scope and the Application ID of Web API A in the authorized client ID
App Registration for Web API A
In Api Permissions, add the User_Impersonation scope of Web API B
From there, the following code will get you connected
Connect-AzAccount -TenantId '584e32bc-214f-4046-89e5-79b7bac9ae75'
$Params = #{
ClientId = '6788d279-fb83-4962-b371-445479875e0e'
ClientSecret = '16cc0f3d88cb4dd189fe6bf8e845982d'
resourceId = 'aeefa559-cb1c-41eb-ac5d-0bcb0bc01eaf'
Scope = 'https://graph.microsoft.com/user.read+offline_access'
}
function Get-AzCustomTokenOnBehalOf {
[CmdletBinding()]
param (
$ClientId,
$ClientSecret,
#Application ID of the target resource
$ResourceId,
$Scope
)
# Get Token For WebApp A $TenantId
$Context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$IntermediaryToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $ClientId).AccessToken
$TokenUri = "https://login.microsoftonline.com/$($Context.Tenant.Id)/oauth2/token"
$FinalToken = Invoke-RestMethod -Uri $TokenUri -Method Post -Body #{
grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
resource = $ResourceId
client_id = $ClientId
client_secret = $ClientSecret
assertion = $IntermediaryToken
scope = $Scope
requested_token_use = 'on_behalf_of'
}
return $FinalToken
}
$Token = Get-AzCustomTokenOnBehalOf #Params
$Headers = #{Headers = #{Authorization = "bearer $($Token.access_token)" } }
$MYsite = Invoke-RestMethod -Method Get -uri 'https://SomeWebsite.com/' #Headers
Additional considerations
This scenario do require a client secret (This is the one I demonstratedO or a client certificate in order to work.
It is also subject to some limitations defined in the reference documentation and might not be suitable to all scenarios.
References:
Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow
I've a problem getting token for my azure application
here is the code
function Get-Token
{
ipmo "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
ipmo "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll"
$clientId = "1b730954-1685-4b74-9bfd-dac224a7b894"
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
$resourceAppIdURI = "https://ios111.azurewebsites.net/"
$authority = "https://login.microsoftonline.com/common/"
$authContext = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]$authority
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId, $redirectUri, "Auto")
$authResult.CreateAuthorizationHeader()
}
I receive the following error
Exception calling "AcquireToken" with "4" argument(s): "AADSTS65005:
Invalid resource. The client has requested access to a resource which
is not listed in the requested permissions in the client's application
registration. Client app ID: 1b730954-1685-4b74-9bfd-dac224a7b894.
Resource value from request: https://ios111.azurewebsites.net/.
Resource app ID: f4c1cc8d-629a-4c7e-836a-120ff078e664. List of valid
resources from app registration: .
However if i change the $resourceAppIdURI to
$resourceAppIdURI = "https://management.core.windows.net/"
It's all ok, and i'm authorized to access my application with received token (if i set Authorization header value to this token), but without roles claim which i define in application manifest for this user and which i want to check.
If i just access my function from browser, after login page redirected me back to a function, there is no a Authorization header specified by browser but ARRAffinity cookie and ClaimsPrincipal.Current.Claims in function context has correct roles claim. So, seems in case of PS, there JWT token acquired by .AcquireToken is deserialized to ClaimsPrincipal.Current without using internal web app logic.
Any ideas how to give PS client a permission to access my app ?
Thanks !
To Get Azuere App Token with the required roles, you need a ClientId and Secret, along with required permissions setup, if admin-consent is needed, you should click the 'Grant Permissions' button on the application properites in the Azure Portal.
Then, if all is set correct, you can get a token like this (with the roles included):
Example for the Microsoft Graph API
$adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
$TenantName = "tenant.onmicrosoft.com"
$ClientId = "d1245516-2bg3-1234-123d-7cd067ff66b4" # Your AppId (Just a sample)
$Secret = "H7dd+PejUddGhuuGYY234Xhhhjs7739iQn112317zg=" # Your App Key Secret (Just a sample)
$AuthId = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential($clientId,$secret)
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
$resourceAppIdURI = "https://graph.microsoft.com"
[uri]$authority = "https://login.windows.net/$TenantName/oauth2/authorize"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$Token = $authResult = $authContext.AcquireToken($resourceAppIdURI, $AuthId)
To Check the token you can use this JWT Token Decoder, to see if it has the required roles:
http://jwt.calebb.net/
Solved !
Thank for the help you guys !
Actually, i had to register native azure application, give it access for my WebApp and use this appId as the clientId in the script above. Using "1b730954-1685-4b74-9bfd-dac224a7b894" as Well Known PowerShell clientId probably possible for standard MS app, but there no way you can grand PS access for you app, at least not from azure portal.
Here is the link https://markscholman.com/2016/08/consuming-azure-api-app-azure-ad-authentication-using-powershell/ with step by step explanation given by WayneYang-MSFT
I am trying to do some very quick tests on Azure Active Directory, and I want to use a Daemon Application to access the Graph API without needing a user present to authenticate. I want to verify that my application registration can successfully authenticate to AAD, that my client secret is valid, and make calls to the AAD Graph API.
I have registered a "Web App/API" in my directory already, and I have set it up to have the appropriate permissions to call the AAD Graph API in the App Only Context. I have also generated an application key/certificate for my app so that I can authenticate as a confidential client.
I want to take a look at my AAD Token, and the output from the Graph API after my call. How can I use PowerShell to quickly accomplish this?
This question is very similar to this one where create a PowerShell script to authenticate as a Native Client Application. However, in this situation, there are some subtle and important differences because you want to authenticate as a confidential client. Specifically, we need to create a Client Credential so that we can authenticate without a user as a Daemon Application.
First you need to download and save the .NET dlls for ADAL. The download link can be found on Nuget.
Note: We specifically use ADAL v2 here.
You can extract the contents of the .nupkg with a File Extractor like
7z, WinZip, etc...
Extract the contents from \lib\net45\ and copy them into your working directory. I put the files in their own "ADAL" folder, to keep it separate.
Then you should be able to create a new PowerShell script with the following:
# Load ADAL
Add-Type -Path ".\ADAL\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
# Output Token and Response from AAD Graph API
$accessToken = ".\Token.txt"
$output = ".\Output.json"
# Application and Tenant Configuration
$clientId = "<AppIDGUID>"
$tenantId = "<TenantID>"
$resourceId = "https://graph.windows.net"
$login = "https://login.microsoftonline.com"
# Create Client Credential Using App Key
$secret = "<AppKey>"
# Create Client Credential Using Certificate
#$certFile = "<PFXFilePath>"
#$certFilePassword = "<CertPassword>"
#$secret = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate -ArgumentList $certFile,$certFilePassword
# Get an Access Token with ADAL
$clientCredential = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential($clientId,$secret)
$authContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("{0}/{1}" -f $login,$tenantId)
$authenticationResult = $authContext.AcquireToken($resourceId, $clientcredential)
($token = $authenticationResult.AccessToken) | Out-File $accessToken
# Call the AAD Graph API
$headers = #{
"Authorization" = ("Bearer {0}" -f $token);
"Content-Type" = "application/json";
}
Invoke-RestMethod -Method Get -Uri ("{0}/{1}/users?api-version=1.6" -f $resourceId,$tenantId) -Headers $headers -OutFile $output
Note: You will need to update the App ID, Tenant ID, and your App Secret information in this script. If you use a certificate to authenticate, simply comment out the code that uses the App Key, and un-comment the code which uses the certificate. I have also pre-configured the AAD Graph API call to return the users in my tenant, but you can change this REST call to whatever you want.
After you successfully run the script, you should get 2 new files in your working directory: A text file that contains your encoded JSON access token, which can be base64 decoded on sites like this, and a JSON file with the response from the AAD Graph API.
Let me know if this helps!