python-requestsaccess-tokenazure-ad-msalmicrosoft-graph-calendar

msal - InvalidAuthenticationToken error appears arbitrarily


I follow stackoverflow for quite some time now. In most cases the problems I encountered were already mentioned and addressed by people before me. Now, I have an issue I have not found an applicable solution to yet. It may result from my humble understanding of the issue and not knowing what I actually am looking for, so I hope you can help me to at least better understand what happens. If additional info is required to make sense, please do not hesitate to ask.

Synopsis: One user of a program I built often (not always, interestingly) gets an InvalidAuthenticationToken error from the request python package when requesting calendar events with a token generated by the msal package while none of the other users have any issues at all.

The situation is as follows: I built a program for a small company which has to read out the events of some of its employees. I wrote it in python and used the msal and requests packages for the part of the interaction with MS Outlook:

import msal
import requests

class OutlookClient():
    def __init__(self, client_id, authority):
        # client_id and authority are the respective 
        # aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee style ids of the app I registered at azure.
        self.app = msal.PublicClientApplication(
                client_id = client_id,
                client_credential = None,
                authority = msal.authority.AuthorityBuilder(msal.authority.AZURE_PUBLIC,authority)
                )

    def getToken(self, username, pw): 
        # credentials of some dummy employee being authenticated to access 
        # the employees' calendars
        self.auth = self.app.acquire_token_by_username_password(username,pw,
                scopes=["Calendars.Read","Calendars.Read.Shared","People.Read"]
                )
        return

   def getCalendar(self, agentCal, startDate, endDate): 
        # agentCal is the id of the employee in question obtained somewhere else.
        graph_data = None
        if 'access_token' in self.auth:
            req = "https://graph.microsoft.com/v1.0/users/"+agentCal+"/calendar/calendarView"+\
                            "?startDateTime="+ startDate.strftime("%Y-%m-%dT02:00")+\
                            "&endDateTime="+ endDate.strftime("%Y-%m-%dT23:00")+\
  
            graph_data = requests.get(req,
                    headers={'Authorization': 'Bearer ' + self.auth['access_token'], 'content-type': 'application/json'}
                    ).json()

        try:
            return graph_data['value']
        except KeyError:
            return []

Currently, three employees are testing the program in the field. One of them faces a recurring error which neither of the other users nor I can reproduce. When getCalendar gets called the request gets answered as

graph_data = 
{'error': 
  {'code': 'InvalidAuthenticationToken', 
   'message': 'Access token has expired or is not yet valid.', 
   'innerError': 
     {'date': '2022-10-27T05:56:39', 
      'request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 
      'client-request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
     }
  }
}

whereas all other users and the specific user also sometimes should get a list of events. The token, however, looked fine to me:

self.auth =
{'token_type': 'Bearer', 
 'scope': 'Calendars.Read Calendars.Read.Shared Calendars.ReadWrite Mail.ReadWrite Mail.Send openid People.Read profile User.Read email', 
 'expires_in': 4581, 
 'ext_expires_in': 4581, 
 'access_token': 'eyJ0eXAiOiJKV1Q...', 
 'refresh_token': '0.AREA...', 
 'id_token': 'eyJ0eXAiOiJKV1Q...', 
 'client_info': 'eyJ1aWQ...', 
 'id_token_claims': {...}
}

I have limited opportunity to identify the issue at the user's computer, unfortunately, as they are currently overwhelmed with work and therefore not very responsive. So, before I bother them and myself with many trial and error approaches I hoped you could share some ideas.

The problem persists, as I was told, even when the program is closed and restarted.

I let the program create a log-file which stores the relevant variables such as the token etc. to see if any pattern arises but everytime a token is generated independent of whether the request for the calendars is answered correctly or incorrectly.

I thought that maybe the program gets started and after some time the token expires but in the log-file it seems to still be valid.


Solution

  • Sorry, it was as expected and I initially just did not check the correct things. Indeed, the token expired and I did not see it. One solution is to check whether a request gets answered properly and if not get a token by the refresh token

    if 'error' in graph_data:
        self.auth = self.app.acquire_token_by_refresh_token(\
            self.auth['refresh_token'],scopes)
    

    and request again.