Office365-REST-Python-Client icon indicating copy to clipboard operation
Office365-REST-Python-Client copied to clipboard

Q: how to deal with token refresh?

Open steffenschumacher opened this issue 2 years ago • 3 comments

We have an API which integrates with Sharepoint, where ideally we don't obtain tokens for each API call. But from what I can tell, there are no infra to handle expiring tokens/refreshing them. Should I:

  • just accept this, or
  • refresh on expiry or
  • do a PR for handing refresh or
  • did miss something, and handling of this is handled somewhere?

PS. I'm basing this on this from TokenResponse:

    def is_valid(self):
        return self.accessToken is not None and self.tokenType == 'Bearer'

Seems not to check anything RE expiry

steffenschumacher avatar Sep 22 '23 08:09 steffenschumacher

Refresh Tokens can be handled by the msal library. It contains a token cache that can be serialized - SerializableTokenCache and then be stored somewhere safe

I'm not sure Refreshing tokens, or storing these forms part of this library, but an example might be useful.

An example of where I use this, is in the aiohttp_msal library: see here for retrieving these from Redis. Although the typical flow would be renewing client tokens based on the Tokencache stored in an aiohttp_session session (mostly using using Redis for the actual storage)

kellerza avatar Oct 03 '23 16:10 kellerza

There are many ways to deal with it, and I’m not arguing that this library should reinvent the wheel, but ideally leverage existing options to deal with expired tokens in some way. I can’t easily see how I would easily inject handling of expired tokens, without touching a fair share of internals of this library?

steffenschumacher avatar Oct 03 '23 18:10 steffenschumacher

Not tested, starting from the function in the readme and adding a token_cache. Stored in clear text.

def acquire_token_func():
    """
    Acquire token via MSAL
    """
    authority_url = 'https://login.microsoftonline.com/{tenant_id_or_name}'
    path = pathlib.Path("/my_token_cache.json")
    token_cache = SerializableTokenCache()
    token_cache.deserialize(path.read_text(encoding="utf8"))
    app = msal.ConfidentialClientApplication(
        authority=authority_url,
        client_id='{client_id}',
        client_credential='{client_secret}'
        token_cache=token_cache
    )
    token = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
    if token_cache.has_state_change:
         cstr = token_cache.serialize()
         path.write_text(cstr, encoding="utf8")
    return token

kellerza avatar Oct 03 '23 23:10 kellerza