Authentication

This tutorial covers both authentication (“who is the user?”) and authorization (“does the authenticated user have the required rights?”).

The most comfortable authentication method is the built-in single sign-on (SSO) via Microsoft Entra ID (previously called Azure AD). You can, however, add your own custom authentication and authorization methods.

Authorization

At the core of the authentication system is the User model. You can find it under app/models/user.py.

To add global authorization, you can implement the User.is_authorized() method. For example, to only allow users with the domain mydomain.com to run custom scripts and custom functions, you could do:

async def is_authorized(self):
    return self.domain == "mydomain.com" if self.domain else False

Likewise, to only authorize users with certain roles, you could write:

async def is_authorized(self):
    return await self.has_required_roles(["xlwings.user", "db.writer"])

Current user object

If you need access to the current user object from a custom script or a custom function, you can use a function parameter with the type hint CurrentUser:

from ..models import CurrentUser

@func
def get_current_user(current_user: CurrentUser):
    return f"The user's domain is {current_user.domain}"

Anonymous user

By default, there is no authentication provider configured (XLWINGS_AUTH_PROVIDERS=[]) and everyone will be able to run custom functions and custom scripts. The current user object will be User(id='n/a', name='Anonymous', email=None, domain=None, roles=[]).

SSO via Microsoft Entra ID

Note

  • Single sign-on (SSO) is only available for Office.js add-ins.

  • Enabling SSO authentication protects the execution of custom scripts and custom functions, but the task pane needs to be handled separately, see below under Task pane authentication.

SSO means that the user’s identity within Office (either a Microsoft account or a Microsoft 365 identity) is used.

Enable SSO

  1. Register your add-in as an app on the Microsoft Identity Platform

  2. Provide the following settings, using your actual ClientID and TenantID that you can find on the Entra ID dashboard:

XLWINGS_AUTH_PROVIDERS=["entraid"]
XLWINGS_AUTH_ENTRAID_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
XLWINGS_AUTH_ENTRAID_TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

To permit users from external organizations, you additionally need to set the following setting to true:

XLWINGS_AUTH_ENTRAID_MULTITENANT=true
  1. Go to the /manifest endpoint and sideload the updated version of the manifest (restart Excel).

  2. Optionally implement an User.is_authorized() method, see Authorization.

Entra ID Roles

Optionally, you can work with roles. On the Azure Dashboard, go to Microsoft Entra ID. On the left side bar under Manage, click on App registrations. Click on the correct app, then:

  • App roles (left sidebar, under Manage):

    • Click on Create app role

    • Display name: e.g. Writer

    • Allowed member types: Users/Groups

    • Value: e.g. Task.Write

    • Description: Writer

    • Checkbox must be active for Do you want to enable this app role?

    • Apply

=> Repeat this step to create other roles.

  • Go all the way back to Microsoft Entra ID, then under Enterprise applications (left sidebar under Manage):

    • Select the previously created application xlwings

    • Click on 1. Assign users and groups

    • Click on Add user/group

      • Under User, click on None Selected and select a user or group. Confirm with Select.

      • Under Role, click on None Selected and select Writer or Reader (if you don’t see any role, wait a moment and reload the page). Confirm with Select.

      • Repeat the last step to give the user both Reader and Writer roles

These roles will be available under User.roles and can be used in order to implement role-based access control (RBAC), see Authorization.

Air-gapped servers

In order to verify the JWT token that Office.js sends to the backend, the backend needs access to the latest version of the Azure JSON Web Key Set (JWKS).

If your application runs on an air-gapped server and can’t download the JWKS directly from the Internet, you can provide your own function under app/auth/entraid/jwks.py to access the JSON file. For example, you could have a cron job that downloads the JSON document once every 24 hours and stores it in a location where the air-gapped server has access.

The URL to retrieve the JWKS JSON file is: https://login.microsoftonline.com/common/discovery/v2.0/keys

Custom authentication

Note

Enabling custom authentication protects the execution of custom scripts and custom functions, but the task pane needs to be handled separately, see below under Task pane authentication.

To use your own authentication method, activate the custom authentication provider:

XLWINGS_AUTH_PROVIDERS=["custom"]

To make this work on the backend, you need to implement the validate_token() function under app/auth/custom/__init__.py.

On the frontend, you need to provide the token depending on your integration:

Task pane authentication

  • The landing page of the task pane needs to be publicly available

  • The rest of the pages can be locked down using the User dependency injection

  • You will need to provide the Authorization header with every request

There is an htmx sample included under app/templates/examples/auth.