3

Within our department we have a Classic ASP website that has been using our corporate Google accounts for authentication and to insert events into our Google Calendars. The organisation has just switched from Google to Office 365 and I'm trying to switch the code to use Outlook instead - with no success.

I can use the access token to GET https://graph.microsoft.com/v1.0/me and see the basic profile, but if I try to read calendar events or send an e-mail I see the message:

"error": {
  "code": "NoPermissionsInAccessToken",
  "message": "The token contains no permissions, or permissions can not be understood."

I created an Azure account with my personal Microsoft account and added an application. I added my colleagues and my corporate account as guest users. I set the permissions required and did the admin consent thing:

Application Permissions

Enterprise Application Permissions

I then followed the steps on this page.

I first visit https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/authorize, including the following query items:

client_id={client id}
response_type=code
redirect_uri={our URL}
response_mode=query
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
state={number}

This returns a "code", which I send to https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/token, including:

grant_type=authorization_code
client_secret={client secret}
client_id={client id}
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
state={same number as above}
redirect_uri={same URL as above}
code={code returned from /authorize}

This returns the id, access and refresh tokens. If I decode the access token using https://jwt.ms/, it seems to contain the appropriate audience and scope:

"aud": "https://graph.microsoft.com"
"scp": "Calendars.ReadWrite email Mail.Send openid profile User.Read"

...although I notice that there is no "roles" entry, which I see in some of the documentation. Is that an issue?

I then send the access token to https://graph.microsoft.com/v1.0/me with the following headers:

"Authorization", "Bearer {access token}"
"Host", "graph.microsoft.com"
"Content-Type", "application/json"
"Prefer", "outlook.timezone Europe/London"

That will return my e-mail address, etc., but if I change the URL to anything else, such as /me/photo/$value, /me/calendar/events, or try to send an e-mail I'm told that there are no permissions in the token.

I see that there are other similar questions, but they are mostly for the client_credentials flow (I'm not sure that makes any difference), and none of the answers has helped me resolve my problem.

Can someone please let me know if I've obviously missed anything - or I'm going about this in the wrong way to access Graph data on the client side? It seemed so straightforward with Google, but I'm finding the Microsoft documentation and examples a bit less detailed.

  • Do you have an Exchange Online mailbox provisioned? – Marc LaFleur Nov 05 '19 at 21:56
  • All of the guest accounts (including the one I'm using to log in with for the testing, and which is giving the error) have mailboxes and calendars - the data was migrated into them from the Google accounts, but things have been added since. The account that's the owner of Azure account doesn't have a mailbox or a calendar, though. If I log in to the web app using that account then I see an unspecified error 500 when trying to use Graph to access the calendar. – JaquesJaquesLiverot Nov 05 '19 at 22:50
  • 1
    Guest accounts are different from normal accounts. Graph cannot access a mailbox in another tenant so if you auth in Tenant A with a guest from Tenant B, it has no way of accessing that user's mailbox. Graph can only speak to a single tenant at a time. – Marc LaFleur Nov 06 '19 at 15:54
  • Thanks for your help - hopefully this will point me in the right direction. The Google solution doesn't have any of this to consider, which is probably why I was struggling - each user is able to give his/her own consent regardless of who created the account. – JaquesJaquesLiverot Nov 07 '19 at 16:21

1 Answers1

1

Adding guest users is meaningless.

What you have done is Admin consent for the Azure AD with your personal Microsoft account.

What you actually need to do is Admin consent for the target Azure AD/ O365 tenant.

Construct a consent link as following:

https://login.windows.net/{tenant ID of the target Azure AD}/oauth2/authorize?response_type=id_token&client_id={client ID}&redirect_uri={reply url}&response_mode=form_post&nonce=a4014117-28aa-47ec-abfb-f377be1d3cf5&resource=https://graph.microsoft.com&prompt=admin_consent

Access it in a browser and log in with an admin account of target Azure AD.

Another issue is that you are using Get access on behalf of a user. So you have to assign Delegated permissions rather than Application permissions in the Azure AD app.

enter image description here

Allen Wu
  • 15,529
  • 1
  • 9
  • 20
  • Thanks - I did wonder whether the problem was related to something like that. I've also just noticed that the details returned by my call to /me aren't the same as those I see in Graph Explorer - presumably because my code is giving details of the guest account and Graph Explorer is showing the original account? I'll give your suggestion a go. Is this stuff explained anywhere? If you don't know what you're missing, then you don't know what to search for! – JaquesJaquesLiverot Nov 06 '19 at 09:45
  • Yes. Graph Explorer will show the information of the original account. You could do the admin consent for the target tenant and call /users/user id. Please let me know if you have any further concerns. – Allen Wu Nov 07 '19 at 01:19
  • Thanks - I'm not an administrator for the target tenant, so now I've got the task of persuading the corporate IT department to sort that out for me. Wish me luck! – JaquesJaquesLiverot Nov 07 '19 at 16:23