1

At the moment I have a working ps1 code that exports the output to a csv locally but I need it to save to a onedrive location as the code needs to be saved and run in Azure function app. These are the steps I have taken so far.

  1. Created a Function App with a unique name, correct location and subscription.

  2. I then created a Function inside that "Function App" called TimeTrigger

  3. Inside "TimeTrigger" I have added my code as a new file called AzureExport.ps1 and then added a line to the bottom of the run.ps1 file as shown below;

    # Input bindings are passed in via param block.
    param($Timer)
    
    # Get the current universal time in the default string format.
    $currentUTCtime = (Get-Date).ToUniversalTime()
    
    # The 'IsPastDue' property is 'true' when the current function 
    invocation is later than scheduled.
    if ($Timer.IsPastDue) {
     Write-Host "PowerShell timer is running late!"
     }
    
     # Write an information log with the current time.
     Write-Host "PowerShell timer trigger function ran! TIME: 
     $currentUTCtime"
    
     # Execute the AzureLastSignInDateCode.ps1 script
     . ./AzureExport.ps1
    
  4. Then I went to "App registration" section of Azure and clicked on "New Registration"

  5. Filled in all my information and noted down the Application (client) ID, Object ID and Directory (tenant) ID.

  6. Finally I clicked on the "Certifactes & secrets", Clicked on "New client secret" gave it a name and then noted down the value and secret ID.

  7. I then took all the IDs that I got and put them into this code that I found to output a token ID

    # Parameters
    $tenantId = "tenantID"
    $client_id = "clientID"
    $client_secret = "client_Secret"
    $scope = "https://graph.microsoft.com/.default"
    $tokenUrl = 
    

    "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"

    # Construct the body of the token request
    $body = @{
        client_id     = $client_id
        scope         = $scope
        client_secret = $client_secret
        grant_type    = "client_credentials"
     }
    
    # Send the token request
    $response = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body 
    

    $body

    # Extract the access token from the response
    $accessToken = $response.access_token
    
    # Use the access token to make authenticated requests to 
    

    Microsoft Graph or other Azure services # For example: $headers = @{ "Authorization" = "Bearer $accessToken" "Content-Type" = "application/json" }

    # Example: Get user profile from Microsoft Graph
    $userProfile = Invoke-RestMethod -Uri 
    

    "https://graph.microsoft.com/v1.0/me" -Method Get -Headers $headers $userProfile

But that is where I got stuck as it through out an error

Invoke-RestMethod : {"error":"invalid_client","error_description":"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'd4eef1b3-cb06-4123-b188-78dfd1bd1b4d'. Trace ID: cc34903e-4bc3-4a5b-b7e3-3555edd4ac00 Correlation ID: ea2c349b-3b10-403d-bcf6-d62a07c31e0d Timestamp: 2024-02-15 08:55:54Z","error_codes":[7000215],"timestamp":"2024-02-15 08:55: 54Z","trace_id":"cc34903e-4bc3-4a5b-b7e3-3555edd4ac00","correlation_id":"ea2c349b-3b10-403d-bcf6-d62a07c31e0d","error_uri":" https://login.microsoftonline.com/error?code=7000215"} At line:17 char:13

  • $response = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $body
  •         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExceptio n
    • FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand Invoke-RestMethod : The remote server returned an error: (400) Bad Request. At line:30 char:16
  • ... erProfile = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/ ...
  •             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExceptio n
    • FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
6
  • You are getting error 400 which means the connection completed including the OAUTH2 authentication. The error 400 could means 1) The Route in the URI has errors 2) The HTTP headers are bad 3) The body/contents is bad 4) There is an inconsistency between the headers and the body. Your server has a frontend and a backend. Since you are getting a 400 error the frontend is connecting. Exception implies the issue is with the credentials being passed from the frontend to the backend have issues. The backend is the server to the database. Commented Feb 15, 2024 at 10:35
  • Can you see any mistakes in my steps that I need to change to correct the error? Commented Feb 15, 2024 at 11:20
  • Everything you posted is good since you are getting error 400. If you are now getting error 404 I think you made the situation worse. Error 404 is Not Found. Which means you don't have permission to access a Route which is a URI issue. There is something wrong with the original code that the permission to access the backend database is wrong. Commented Feb 15, 2024 at 13:08
  • The title says "schedule". What does that mean? Are you running the PS as a Task? The error could mean that you need to run the task As A User (or Admin). The default for a scheduled task is a system account with no Environment. Normally scheduled task are run from a service account with an environment. Commented Feb 15, 2024 at 14:00
  • I am trying to run the powershell script every Monday at 08:00 and save the output on the onedrive. Commented Feb 15, 2024 at 14:19

1 Answer 1

1

To invoke GET https://graph.microsoft.com/v1.0/me, you need to have Authorization code grant type in place. In order to use client_credentials grant type, you can invoke GET https://graph.microsoft.com/users/{id | userPrincipalName} as per the documentation and grant
User.Read.All Application permission type.

I have used the below code to get the User Profile Information. Here I am using GET /users/{id | userPrincipalName} endpoint.

# Input bindings are passed in via param block.
param($Timer)

# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()

# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
    Write-Host "PowerShell timer is running late!"
}

# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"

# Parameters
$tenantId = "{tenantId}"
$client_id = "{client_id}"
$client_secret = "{client_secret}"
$scope = "https://graph.microsoft.com/.default"
$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"

# Construct the body of the token request
$body = @{
    client_id     = $client_id
    scope         = $scope
    client_secret = $client_secret
    grant_type    = "client_credentials"
 }

# Send the token request
$response = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $body

# Extract the access token from the response
$accessToken = $response.access_token

# Use the access token to make authenticated requests to Microsoft Graph or other Azure services 
$headers = @{
     "Authorization" = "Bearer $accessToken"
     "Content-Type" = "application/json" 
    }

# Example: Get user profile from Microsoft Graph
$userProfile = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/users/{userPrincipalName}" -Method Get -Headers $headers 


Write-Host "User Profile Data: $userProfile"

Please ensure to use the secret value from value field showing in Certificates and secrets blade and add User.Read.All Application permission in API Permissions blade.

I am able to get the user data successfully.

enter image description here

Sign up to request clarification or add additional context in comments.

11 Comments

I have just tried to run your code with my credentials put in place and I am now getting a 403 forbidden error. Invoke-RestMethod : The remote server returned an error: (403) Forbidden. At ..... + ... erProfile = Invoke-RestMethod -Uri "graph.microsoft.com/v1.0 ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I have ran the code on Powershell ISE administrator
Have you granted user.read.all permission to the registered app?
Yes, I have checked and under API permissions I am getting; under Microsoft Graph User.Read.All Application Read all users' full profiles Yes Granted for ....
I have just run it again and I am now getting a 404 error
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.