3

I've been having a hell of a time trying to access the Microsoft Graph using PowerShell.

First I tried using the authorization flow and Invoke-WebRequest and Invoke-RestMethod neither of which I could get to work.

Then I found this blog that showed how to do it using PowerShell and a couple of the Azure modules. Below is the code I'm using (ripped right from that blog) but every time I get to the Invoke-RestMethod (in the do-while loop) instead of getting the result of the query I get a 403 Forbidden error:

Invoke-RestMethod : The remote server returned an error: (403) Forbidden.

Function GetAuthToken {
    Param (
        [Parameter()]
        $TenantName
    )
    Import-Module Azure
    $clientId = "1950a258-227b-4e31-a9cf-717495945fc2"
    $resourceAppIdURI = "https://graph.microsoft.com"
    $authority = "https://login.microsoftonline.com/$TenantName"
    $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
    $Credential = Get-Credential
    $AADCredentialUser = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential" -ArgumentList $credential.UserName, $credential.Password
    $authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId, $AADCredentialUser)
    Write-Output $authResult
}

Function GetAllObjectOfType {
    param
    (
        [Parameter(Mandatory = $true)]
        $Tenant,
        [Parameter(Mandatory = $true)]
        $Type,
        [Parameter(Mandatory = $false)]
        $BatchSize = 100,
        [Parameter(Mandatory = $false)]
        $Version = 'Beta'
    )

    #------Get the authorization token------#
    $token = GetAuthToken -TenantName $tenant

    #------Building Rest Api header with authorization token------#
    $authHeader = @{
        'Content-Type'  = 'application/json'
        'Authorization' = $token.CreateAuthorizationHeader()
    }

    #------Initial URI Construction------#
    #$uritest = "https://graph.microsoft.com/v1.0/users/[email protected]/mailFolders/Inbox/childFolders"
    $uritest = "https://graph.microsoft.com/v1.0/me/mailFolders/Inbox"
    #Join-Path -Path ''
    $ObjCapture = @()
    do {
        $users = Invoke-RestMethod -Uri $uritest -Headers $authHeader -Method Get
        $FoundUsers = ($Users.value).count
        write-host "URI" $uri " | Found:" $FoundUsers
        #------Batched URI Construction------#
        $uri = $users.'@odata.nextlink'
        $ObjCapture = $ObjCapture + $users.value

    }until ($uri -eq $null)
    $ObjCapture
}

I can run this same query (/v1.0/me/mailFolders/Inbox) from the Graph Explorer and it runs perfectly fine with no errors.

The GetAuthToken seems to be working as I do get a token back with an expiry, refresh token, etc and the $token.CreateAuthorizationHeader() also returns the correct Authorization = Bearer token

I've never done anything with the Microsoft Graph before so I'm sure there is something I'm doing wrong but I cannot for the life of me figure out what.

2
  • Could you add the token you received as well as the steps you took to obtain your clientId (including the scopes/permissions)? Commented Jan 31, 2018 at 17:27
  • @MarcLaFleur-MSFT Actually the clientId is the same one used in the article I got the steps from (so I'm assuming that is not correct). I'm not sure what you mean by can I add the token. Add it to a comment? Commented Jan 31, 2018 at 20:16

4 Answers 4

3

You cannot reuse the clientid from that blog post. You need to obtain your own clientid by registering your application. See Register your app with the Azure AD v2.0 endpoint for details on how to register your app.

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

3 Comments

Do I need to register an app even if I'm using my own credentials to access the graph? I created an app in the Azure portal and I tried using the clientid and clientsecret of it with a Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential object. Then using that object to create the authtoken using $authContext.AcquireToken($resourceAppIdURI,$AADCredentialApps) but I couldn't get that working either, it came back with the same error message.
Every application needs an App/Client ID in order to authorize it. In order to use Client Credentials, you will need both the Client ID/Secret and Admin Consent. See developer.microsoft.com/en-us/graph/docs/concepts/… for an explanation of how this works.
If I'm not using the v2 endpoint for the authentication I can grant that admin consent through the Azure AD Blade in the Azure Portal can I not? I guess maybe what I'm not understanding is the code above is using the v2 endpoint. Is that accurate? And if so I'd have to go through the Microsoft App Registration Portal to create the app and grant permissions...
1

This seems like it was answered in a follow-up blog post from the same source.

When an App is created, by default it has rights to access only the data of the user that had signed in with the account though the “Sign in and read user profile” delegated permissions. If you try to execute a script that uses this AppID/ClientID to query Azure AD to get a list of all users in the directory, you would receive an error stating (403) Forbidden because it didn’t have adequate permissions to do that activity.

Comments

0

Putting this here in case any other wandering devs come across the post like I did. Here's the powershell function I'm using to get the access token from our tenant. ClientId and Secret are created in the Azure App Registrations, like others have mentioned.

$clientId = $args[0]
$secret = $args[1]
$redeemURI = "https://login.microsoftonline.com/{tenantGuid}/oauth2/v2.0/token"

$body = "client_id=$clientId&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=$secret&grant_type=client_credentials"

$response = Invoke-RestMethod -Method Post -Uri $redeemURI -Body $body -ContentType "application/x-www-form-urlencoded"

return $response.access_token

Usage:

$token = ./GetAccessToken.ps1 "{clientId}" "{secret}"

Comments

-1

I think it needs AD Azure Premium 2 licences enter link description here

Comments

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.