Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Microsoft Graph The token contains no permissions, or permissions cannot be understood

I am working with Microsoft Graph and have created an app that reads mail from a specific user.

However, after getting an access token and trying to read the mailfolders, I receive a 401 Unauthorized answer. The detail message is:

The token contains no permissions, or permissions cannot be understood.

This seems a pretty clear message, but unfortunately I am unable to find a solution. This is what I have done so far:

  • Registering the app on https://apps.dev.microsoft.com
  • Giving it application permissions Mail.Read, Mail.ReadWrite (https://learn.microsoft.com/en-us/graph/api/user-list-mailfolders?view=graph-rest-1.0)

  • Have gotten administrator consent. enter image description here

The permissions are: enter image description here enter image description here - Written the code below to acquire an access token:

 // client_secret retrieved from secure storage (e.g. Key Vault)
 string tenant_id = "xxxx.onmicrosoft.com";
 ConfidentialClientApplication client = new ConfidentialClientApplication(
 "..",
 $"https://login.microsoftonline.com/{tenant_id}/",
 "https://dummy.example.com", // Not used, can be any valid URI 
 new ClientCredential(".."),
 null, // Not used for pure client credentials
 new TokenCache());
   string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
   AuthenticationResult result = client.AcquireTokenForClientAsync(scopes).Result;
   string token = result.AccessToken;

So far so good. I do get a token.

Now I want to read the mail folders:

url = "https://graph.microsoft.com/v1.0/users/{username}/mailFolders";
handler = (HttpWebRequest)WebRequest.Create(url);
handler.Method = "GET";
handler.ContentType = "application/json";
handler.Headers.Add("Authorization", "Bearer " + token);
response = (HttpWebResponse)handler.GetResponse();
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
    returnValue = sr.ReadToEnd();
}

This time I receive a 401 message, with the details:

The token contains no permissions, or permissions cannot be understood.

I have searched the internet, but can’t find an answer to why my token has no permissions.

Thanks for your time!

update 1

If I use Graph Explorer to read the mailfolders, then it works fine. Furthermore: if I grap the token id from my browser en use it in my second piece of code, then I get a result as well. So, the problem is really the token I receive from the first step.

like image 518
Roeland Avatar asked Jan 17 '19 11:01

Roeland


1 Answers

To ensure this works like you expect, you should explicitly state for which tenant you wish to obtain the access token. (In this tenant, the application should, of course, have already obtained admin consent.)

Instead of the "common" token endpoint, use a tenant-specific endpoint:

string url = "https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token";

(Where {tenant-id} is either the tenant ID of the tenant (a Guid), or any verified domain name.)

I would also strongly recommend against building the token request on your own, as you show in your question. This may be useful for educational purposes, but will tend to be insecure and error-prone in the long run.

There are various libraries you can use for this instead. Below, an example using the Microsoft Authentication Library (MSAL) for .NET:

// client_secret retrieved from secure storage (e.g. Key Vault)
string tenant_id = "contoso.onmicrosoft.com";
ConfidentialClientApplication client = new ConfidentialClientApplication(
    client_id,
    $"https://login.microsoftonline.com/{tenant_id}/",
    "https://dummy.example.com", // Not used, can be any valid URI 
    new ClientCredential(client_secret),
    null, // Not used for pure client credentials
    new TokenCache());

string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
AuthenticationResult result = client.AcquireTokenForClientAsync(scopes).Result
string token = result.AccessToken;
// ... use token
like image 162
Philippe Signoret Avatar answered Oct 23 '22 15:10

Philippe Signoret