1 of 5 requests to Graph API /users/licensedetails fail with 401 Unauthorized

Tobias Ask 26 Reputation points Microsoft Employee
2023-01-02T11:14:35.34+00:00

Hi, I'm on a team that works on an internal Microsoft service. We are calling the Graph /users/licensedetails endpoint in a background processing context to get the user's licenses, and it fails roughly 1/5 of the time with 401 Unathorized responses; otherwise, it succeeds. We have set up auth with an application permission to the default scope, and we are using MSAL in .NET Core to get tokens. My best guess would be that the error is caused by expired tokens since it works 4/5 times, but then I also understand that MSAL should handle renewal automatically, so I'm hoping to get some help here.

Here are details from the headers of a 401 response:

  • request-id: 5fe76a9b-a2b2-4ef9-b093-64388558d5dd
  • Date: Mon, 02 Jan 2023 10:09:15 GMT
  • x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"North Central US","Slice":"E","Ring":"3","ScaleUnit":"005","RoleInstance":"CH01EPF00016950"}}
  • client-request-id: 6a157167-3989-4bfe-944e-6eac76517e65
Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,679 questions
{count} votes

Accepted answer
  1. CarlZhao-MSFT 37,216 Reputation points
    2023-01-04T09:44:26.867+00:00

    Hi @Tobias Ask

    I can't reproduce your issue locally, but as I said in a comment, there are many reasons for a 401 error, not necessarily due to token expiration. The best practice is to capture the full error message to find your issue.

    I have used the graph C# SDK to call the /licensedetails endpoint many times and it works fine, please refer to my sample code:

    276031-image.png

    using Azure.Identity;   
    using Microsoft.Graph;  
    using Newtonsoft.Json;  
      
    try  
    {  
          var scopes = new[] { "https://graph.microsoft.com/.default" };  
      
          var tenantId = "tenant id";  
      
          // Values from app registration  
          var clientId = "client id";  
          var clientSecret = "client secret";  
      
          // using Azure.Identity;  
          var options = new TokenCredentialOptions  
          {  
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud  
          };  
      
          // https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential  
          var clientSecretCredential = new ClientSecretCredential(  
                tenantId, clientId, clientSecret, options);  
      
          var graphClient = new GraphServiceClient(clientSecretCredential, scopes);  
      
          var licenseDetails = await graphClient.Users["user id"].LicenseDetails.Request().GetAsync();  
      
          Console.WriteLine("licenseDetails:" + JsonConvert.SerializeObject(licenseDetails));  
    }  
    catch (Exception ex)  
    {  
        Console.WriteLine(ex);  
    }  
    

    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


4 additional answers

Sort by: Most helpful
  1. Vicky Kumar (Mindtree Consulting PVT LTD) 1,156 Reputation points Microsoft Employee
    2023-01-02T17:03:38.607+00:00

    Thanks for reaching out to us, this might be due to token expiration, the expiry time of the token is about one hour, you can try the doc to Refresh token lifetime - https://learn.microsoft.com/en-us/azure/active-directory/develop/refresh-tokens . Hope this helps.

    0 comments No comments

  2. Gopinath Chennamadhavuni 2,431 Reputation points
    2023-01-03T07:39:43.89+00:00

    Hi @Tobias Ask ,

    Thank you for reaching out to us. As I see you are getting error 401 while performing GET /users/licensedetails to Graph API.

    Error 401 is an Unauthorized error. Make sure that your application is presenting a valid access token to Microsoft Graph as part of the request. This error often means that the access token may be missing in the HTTP authenticate request header or that the token is invalid or has expired.

    We strongly recommend that you use the Microsoft Authentication Library (MSAL) for access token acquisition.

    Hope this helps.

    If the answer is helpful, please click /users/licensedetails and kindly upvote. If you have any further questions about this answer, please click Comment.


  3. Tobias Ask 26 Reputation points Microsoft Employee
    2023-01-03T11:21:47.49+00:00

    Thanks for your replies. We can start to log the error code (as described here https://learn.microsoft.com/en-us/graph/errors?view=graph-rest-1.0#code-property) from the response body as @CarlZhao-MSFT suggests.

    @Gopinath Chennamadhavuni :

    Error 401 is an Unauthorized error. Make sure that your application is presenting a valid access token to Microsoft Graph as part of the request. This error often means that the access token may be missing in the HTTP authenticate request header or that the token is invalid or has expired.

    We always include the token in the Authorization request header. The success rate of roughly 80% indicates that the request is formed correctly.

    We strongly recommend that you use the Microsoft Authentication Library (MSAL) for access token acquisition.

    We are using MSAL for .NET Core to get tokens. As I understand, the library should automatically renew expired tokens.

    Are any of you able to check the logs for the specific request I've posted details about?

    0 comments No comments

  4. Tobias Ask 26 Reputation points Microsoft Employee
    2023-01-06T08:12:59.287+00:00

    Root cause that was masking the simpler error was using the "https://login.microsoftonline.com/<USER_TENANT_ID>" authority URL when getting tokens from MSAL, instead of the one meant for multitenant apps, "https://login.microsoftonline.com/organizations/".

    0 comments No comments