AzureAD / microsoft-authentication-library-for-python

Microsoft Authentication Library (MSAL) for Python makes it easy to authenticate to Microsoft Entra ID. General docs are available here https://learn.microsoft.com/entra/msal/python/ Stable APIs are documented here https://msal-python.readthedocs.io. Questions can be asked on www.stackoverflow.com with tag "msal" + "python".
https://stackoverflow.com/questions/tagged/azure-ad-msal+python
Other
770 stars 192 forks source link

Short max_age can trigger re-auth, but also results in short lived token. How do we get tokens for longer time? #444

Closed raqsilva closed 10 months ago

raqsilva commented 2 years ago

Hello,

This regards to the new feature of maximum authentication age (max_age) when initiating the auth flow (initiate_auth_code_flow) for a confidential client application.

We are expecting the user to be forced to re-authenticate if they haven't done that after max_age seconds. This part works perfectly fine, if we set the max_age to 0 seconds it will prompt the re-auth right away and if we set to 120 secs it will only prompt the re-auth if the user have not authenticated in the past 120 secs plus.

Although, if we set max_age to any value, this will also change the "exp" claim of our token. Which means if we take just a bit longer on our authentication flow, the token will be expired by then...

The expiration claim should be defined always by our azure application and not by our msal flow, we should only be able to control re-auth and not token expiry date.

msal version = 1.16.0 python version = 3.8.12

rayluo commented 2 years ago

Welcome back, @raqsilva ! Unfortunately, what you discovered is an existing behavior in the Microsoft Identity Platform. MSAL as a client-side library does not have a way to change that. Do you have another channel to contact a Microsoft representative? (CC: @hpsin)

Meanwhile, this workaround might work. You may try to use max_age to trigger the re-auth, and then use MSAL's acquire_token_silent(...) as usual, which can probably get an access token with normal exp. (I haven't tested this hypothesis, though.)

raqsilva commented 2 years ago

Thanks! Indeed not an ideal or even expected behaviour. Do you know how/where in the flow does that change happen?

Sadly for our use case that might not work.

rayluo commented 2 years ago

Thanks! Indeed not an ideal or even expected behaviour. Do you know how/where in the flow does that change happen?

Like I said in my previous message, that change will not be in this library.

Sadly for our use case that might not work.

How so? What kind of app are you building? Each of our sample for the supported scenario includes the acquire_token_silent(), which is the major purpose of the MSAL library in the first place.

We would like to know more about your app and see how we can help.

raqsilva commented 2 years ago

I understand how it seems odd, but that was a way for us to force re-auth when the user has logged out of our app.

We do not have accounts or cache anymore in that stage, that is why we need to get a new one by acquire_token_by_auth_code_flow. Basically the user has logged out of the app but not Microsoft.

Out of curiosity, where are the code samples that use max_age?

rayluo commented 2 years ago

Out of curiosity, where are the code samples that use max_age?

There is no official sample for max_age. It is just an optional parameter that can be added into any existing sample which uses either initiate_auth_code_flow() (i.e. web app) or acquire_token_interactive() (i.e. desktop app).

I understand how it seems odd, but that was a way for us to force re-auth when the user has logged out of our app.

We do not have accounts or cache anymore in that stage, that is why we need to get a new one by acquire_token_by_auth_code_flow. Basically the user has logged out of the app but not Microsoft.

It is not odd for an app to sign out user. But that shouldn't prevent you from utilizing token cache. My hypothesis meant to say:

  1. You use a short max_age (such as 300) to trigger a re-auth.
  2. Although the returned access token (AT) would unfortunately be short-lived (as you've found out), but there is likely a refresh token (RT) also comes back, cached by MSAL.
  3. So, when the AT in step 2 quickly times out, you could make an acquire_token_silent(["same_scope"]) call, as usual, and the RT is expected to kick in and get you a new AT, probably a long-lived one this time.
raqsilva commented 2 years ago

I see what you mean now.

So in your example a max_age of 300 will very likely work, since that is plenty of time for us to get the AT and verify. Although, in our case, if you set the max_age to 0 this will not be possible. So as a workaround we have set it to 60, which is less than your skew of 2min . This gives us the ability to force re-auth, verify the AT and get a new AT after the first one that is very short lived.