Shawn Eary
Shawn Eary

Reputation: 750

Get Access_Token from Microsoft Graph API via cURL

When I run this command in Cygwin per [1] and [2], I get back an Access_Token:

curl -X POST -d 'grant_type=client_credentials&client_id=[myClientId]&client_secret=[myAppSecret]&scope=openid profile User.ReadWrite User.ReadBasic.All Sites.ReadWrite.All Contacts.ReadWrite People.Read Notes.ReadWrite.All Tasks.ReadWrite Mail.ReadWrite Files.ReadWrite.All Calendars.ReadWrite' https://login.microsoftonline.com/[myTenantId]/oauth2/token

When I later try to use that access_token in this trivial query, I get an error:

Access token validation failure. Invalid audience

curl -X GET -H "Authorization: Bearer [accessTokenFromPreviousCommand]" https://graph.microsoft.com/v1.0/me

If I run the https://graph.microsoft.com/v1.0/me query inside Microsoft Graph Explorer, it works correctly. I can also use the Network tab of my internet browser to grab an existing access_token and use that grabbed token in the second cURL command to get back the expected results; however, I have not yet figured out how to successfully take the access_token returned from the first cURL command and use it in the second cURL command.

I did talk to a fellow developer internally about this and he mentioned that I look at [2], but I'm still a bit confused.

Will someone kindly show me what I am doing wrong in the above two cURL commands?

[1] - Mauri, Davide
Calling Azure REST API via cURL
Medium.com
May 4, 2018 [Online]
https://medium.com/@mauridb/calling-azure-rest-api-via-curl-eb10a06127
[Accessed: December 3, 2019]

[2] - Woods, Jackson; Graham, Laura; Guzman, Celeste; Angelgolfer; Wike, Ryan; and possible future contributors
Authentication and Authorization Basics for Microsoft Graph
Microsoft Docs - Microsoft Graph
September 19, 2019 [Online]
https://learn.microsoft.com/en-us/graph/auth/auth-concepts
[Accessed: December 3, 2019]

Upvotes: 2

Views: 13330

Answers (2)

Shawn Eary
Shawn Eary

Reputation: 750

I agree with Mr. LaFleur. Per [3], there appear to be two different workflows for getting an Access Token:

  1. “Get Access on Behalf of a User” [4]
  2. “Get Access Without a User” [5]

I was apparently trying to mix the two workflows due to my lack of understanding. In my case, the “Get Access on Behalf of a User” workflow may have been the most appropriate. As Mr. LeFleur and [4] both point out, the grant type cannot be set to Client Credentials when using the “Get Access on Behalf of a User” workflow shown in [4]. Instead, the grant_type should be set to authorization_code. There was one other major detail that I missed though. Per [4], you also have to run a GET request to acquire an Authorization Code from the user. An example of this GET request is shown below:

https://login.microsoftonline.com/[yourTenantId]/oauth2/v2.0/authorize?client_id=[yourClientId]&response_type=code&response_mode=query&scope=user.read&state=[apparentlyThisIsJustSomeRandomNumber]

Unfortunately, I’m not aware of how to use cURL for that above GET request since it is interactive; however, it’s easy enough to paste the said GET request into the URL Window on your Internet Browser and then click yes on any possible consent dialogs. Once you have granted consent, your browser will be directed to a URL for your app that will contain a “code” value in your query parameters. That URL might look something like this:

https://[locationOfYourApp]/?code=[bigLongUglyAuthCode]&state=[theStateValueYouSetPreviously]&session_state=[junkThatDoesNotMatterInThisExample]

You need to grab that code and then put it in a cURL command of this format (Refer to [4]):

    curl -X POST -d 'grant_type=authorization_code&client_id=[yourClientId]&client_secret=[yourAppSecret]&scope=User.Read&code=[bigLongUglyAuthCodeFromAbove]' https://login.microsoftonline.com/[yourTenantId]/oauth2/token

You should then get a response back that contains an valid Access Token for /me based queries like the one I asked about on Dec 3. The Access Token will work if you insert it into this query in a timely fashion:

    curl -X GET -H "Authorization: Bearer [accessTokenFromPreviousCommand]" https://graph.microsoft.com/v1.0/me

[3] – Microsoft and Community
Microsoft Graph Documentation
[Online]
https://learn.microsoft.com/en-us/graph/
[Accessed: December 4, 2019]

[4] – Thake, Jeremy; Office GSX; Graham, Laura; Woods, Jackson; Allen, Calvin; kjyam98 (Kevin); Wike, Ryan; and possible future contributors
Get Access on Behalf of a User
September 19, 2019 [Online]
https://learn.microsoft.com/en-us/graph/auth-v2-user
[Accessed: December 4, 2019]

[5] – Thake, Jeremy; Woods, Jackson; Office GSX; kjyam98 (Kevin); Graham, Laura; Wike, Ryan; and possible future contributors
Get Access without a User
September 19, 2019 [Online]
https://learn.microsoft.com/en-us/graph/auth-v2-service
[Accessed: December 4, 2019]

Upvotes: 1

Marc LaFleur
Marc LaFleur

Reputation: 33132

You cannot use /me when you authenticate with Client Credentials. You need to specify the user by id or userPrincipalName.

When Graph sees /me, it replaces that node with "the id of the currently authenticated user". Since you don't have an authenticated user when you're using Client Credentials, there is no way for Graph to know which user you're looking for.

Upvotes: 4

Related Questions