Utilizing Django Cache for Office 365's Token Backend

Tuesday, February 13, 2024

Microsoft's O365 python library offers developers a quick an easy tool for interacting with Graph APIs. I won't get into details here, but I highly recommend that you check out the documentation for its capabilities. In this post, I will be covering the library's ability to utilize a custom token cache backend and how you can hook it into Django's cache.

Before getting started, ensure that the Django cache framework is set up. In my project, I decided to use Memcached with the following configuration:

    "default": {
        "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
        "LOCATION": "{0}:{1}".format(env('CACHE_HOST'), env('CACHE_PORT')),

Now we can create our custom token backend. The first step is to set up a sublcass that inherits from BaseTokenBackend:

from O365.utils import BaseTokenBackend

class DjangoCacheTokenBackend(BaseTokenBackend):

    def __init__(self):

Now to actually utilize the cache, two methods must be implemented:

  1. load_token: Loads the token from the backend and will either return a Token instance or None
  2. save_token: Stores the token in the backend

I also recommend implementing the following optional methods:

  1. delete_token: Deletes the token from the backend
  2. check_token: Returns a boolean representing the presence of the token in the backend


With the Django cache framework setup, the default cache can be imported and used within the class. A default key token_key is set up in the constructor and it will be used with all interactions. The following code contains the entire Django cache token backend:

from django.core.cache import cache
from O365.utils import BaseTokenBackend

class DjangoCacheTokenBackend(BaseTokenBackend):

    def __init__(self):
        self.token_key = 'token'

    def load_token(self):
        token = cache.get(self.token_key)
        if token:
            token = self.token_constructor(self.serializer.loads(token))
        return token
    def save_token(self):
        if self.token is None:
            raise ValueError('You have to set the "token" first.')

        cache.set(self.token_key, self.serializer.dumps(self.token), 3600)

        return True
    def delete_token(self):
        return True
    def check_token(self):
        return cache.get(self.token_key) is not None


When setting up the account with o365, simply import the class, initiatlize it and pass it as the token_backend parameter:

from .token import DjangoCacheTokenBackend

credentials = (env('O365_CLIENT'), env('O365_SECRET'))
token_backend = DjangoCacheTokenBackend()
account = Account(credentials, 
Running on recycled hardware from my closet