Previously I have written a number of posts on interacting with Azure AD using the Microsoft Authentication Libraries (MSAL) and Python. This page here lists those posts along with a series using PowerShell. The Python related posts also detail decoding Azure AD access tokens with Python to determine when the access token will expire. In order to achieve that the PyJWT package is used.
When I wrote those articles PyJWT was at version 1.7.x. Subsequently the PyJWT package has been updated and the decode function in my examples no longer works. The posts referenced above make note that version 1.7.x is required.
I haven’t used Python much in the last year but have had to in the last week. Of course, it was with Azure, and I needed logic to manage refreshing the access token. It was rather timely that AussieDavo had posted a comment on one of my posts with a fix for using PyJWT 2.x.
With a few additional modifications I was able to update one of my previous examples and retrieve the expiry time, but also determine the time to expiry relative to current time. Again, there are a few changes to the format of results from PyJWT that required a couple of tweaks.
The key changes to using PyJWT 2.x for decoding Azure AD Access Tokens with Python is to use the get_unverified_header function to retrieve the algorithm of the access token then use the decode function to decode it. The decode function requires the algorithms option to specify the encoding.
To determine the relative expiry time of the access token I’m now not using the msal_jwt_expiry function that I had in some of my examples. Instead, I’m taking the unix datetime formatted exp value from the access token and converting it to datetime relative to UTC. And subtracting the current datetime (in UTC) from that access token expiry.
The following graphic shows these changes and the output. A full example of a script is further below.
The following script is an updated example of my post showing how to authenticate and query Microsoft Graph using MSAL with Python using application permissions and certificate based authentication.
You will need the same dependencies but no longer need to use the deprecated version of PyJWT.
pip install msal json pyjwt requests datetime
You will need to update the following variables near the top of the script below.
- your tenantID (tenant GUID) or tenant name (yourTenant.onmicrosoft.com), of your registered Azure AD Application
- clientID of your registered Azure AD Application
- thumbprint of the uploaded certificate on the registered Azure AD application
- certfile for the local location of your certificate
- scope for your scope(s) associated with your registered Azure AD Application
- queryUser that you will perform a test query for after authentication
Thanks to AussieDavo for posting a comment on my blog. A relatively simple fix now also documented for anyone else trying to use the latest version of PyJWT.