|
| 1 | +--- |
| 2 | +title: Using MSAL Python with Windows Subsystem for Linux |
| 3 | +description: Learn how to integrate Microsoft Entra ID authentication in WSL apps using MSAL Python and the Microsoft Single Sign-on for Linux broker. |
| 4 | +author: ploegert |
| 5 | +ms.author: jploegert |
| 6 | +ms.service: msal |
| 7 | +ms.topic: how-to |
| 8 | +ms.date: 05/08/2025 |
| 9 | +--- |
| 10 | + |
| 11 | +# Enable SSO in WSL (Windows Subsystem for Linux) apps using MSAL Python and WAM |
| 12 | + |
| 13 | +MSAL is able to call the Microsoft Single Sign-on to Linux, a Linux component that is shipped independent of the Linux Distribution, however it gets installed using a package manager using `sudo apt install microsoft-identity-broker` or `sudo dnf install microsoft-identity-broker`. |
| 14 | + |
| 15 | +This component acts as an authentication broker allowing the users of your app to benefit from integration with accounts known to Linux, such as the account you signed into your Linux sessions for apps that consume from the broker. It's also bundled as a dependency of applications developed by Microsoft, such as [Company Portal](/mem/intune-service/user-help/enroll-device-linux). These applications are installed when a Linux computer is enrolled in a company's device fleet via an endpoint management solution like [Microsoft Intune](/mem/intune/fundamentals/what-is-intune). |
| 16 | + |
| 17 | +Using an authentication broker on Linux enables you to simplify how your users authenticate with Microsoft Entra ID from your application, and take advantage of future functionality that protects Microsoft Entra ID refresh tokens from exfiltration and misuse. |
| 18 | + |
| 19 | +To enable SSO in your WSL app using MSAL Python, you must ensure the keychain is set up and unlocked, as MSAL uses `libsecret` to communicate with the keyring daemon. |
| 20 | + |
| 21 | +## WSL Authentication Flow Example |
| 22 | + |
| 23 | +In a situation where you have a WSL app that needs to authenticate with Microsoft Entra ID, the authentication flow for an interactive request would look like this: |
| 24 | + |
| 25 | + |
| 26 | + |
| 27 | +## Update to the latest version of WSL |
| 28 | + |
| 29 | +Ensure you have updated to the latest WSL release. The WAM Account Control dialog is supported in WSL versions 2.4.13 and above. |
| 30 | + |
| 31 | +```powershell |
| 32 | +# To check what distros are available: |
| 33 | +wsl.exe --list --online |
| 34 | +
|
| 35 | +wsl.exe --install Ubuntu-22.04 |
| 36 | +
|
| 37 | +# To check the WSL version: |
| 38 | +wsl --version |
| 39 | +
|
| 40 | +# To update WSL: |
| 41 | +wsl --update |
| 42 | +``` |
| 43 | + |
| 44 | +## Linux Package Dependencies |
| 45 | + |
| 46 | +Install the following dependencies on your Linux platform: |
| 47 | + |
| 48 | +- `libsecret-tools` is required to interface with the Linux keychain |
| 49 | + |
| 50 | +### [Ubuntu](#tab/ubuntudep) |
| 51 | + |
| 52 | +To install on debian/Ubuntu based Linux distribution: |
| 53 | + |
| 54 | +```bash |
| 55 | +sudo apt install libsecret-1-0 -y |
| 56 | + |
| 57 | +#from Powershell, run |
| 58 | +wsl.exe --shutdown |
| 59 | +``` |
| 60 | + |
| 61 | +### [Red Hat Enterprise Linux](#tab/rheldep) |
| 62 | + |
| 63 | +To install on Red Hat/Fedora based Linux distribution: |
| 64 | + |
| 65 | +```bash |
| 66 | +sudo dnf install libsecret-1-0 -y |
| 67 | + |
| 68 | +#from Powershell, run |
| 69 | +wsl.exe --shutdown |
| 70 | +``` |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +> [!IMPORTANT] |
| 75 | +> In order for the keychain to work as intended, you should make sure you 1. install the dependencies, 2. Reboot/restart wsl, 3. Configure the keychain. Failure to do the steps in the correct order will result with the keychain missing the option for "Password Keychain". |
| 76 | +
|
| 77 | +## Set up Keyring in WSL |
| 78 | + |
| 79 | +MSAL uses `libsecret` on Linux. It's required to communicate with the `keyring` daemon. Users can use [Seahorse](https://wiki.gnome.org/Apps/Seahorse/) (a GNOME application for managing encryption keys and passwords) to manage the `keyring` contents through a Graphical User Interface (GUI). |
| 80 | + |
| 81 | +On Debian-based distributions, you can install the package by running `sudo apt install seahorse` and then following these instructions: |
| 82 | + |
| 83 | +1. Run `seahorse` in the terminal as a regular user (not as sudo) |
| 84 | + |
| 85 | +  |
| 86 | + |
| 87 | +2. In the top left corner, select **+** and create **Password** keyring. |
| 88 | + |
| 89 | +  |
| 90 | + |
| 91 | +3. Create a keyring named 'login' |
| 92 | + |
| 93 | +  |
| 94 | + |
| 95 | +4. Set the password on the next dialog. |
| 96 | +  |
| 97 | + |
| 98 | +5. Run `wsl.exe --shutdown` from your Windows Terminal. |
| 99 | + |
| 100 | +6. Start a new WSL session and run the sample. You should be asked for the keyring password. |
| 101 | + |
| 102 | +## Run a Sample App |
| 103 | + |
| 104 | +To use a broker on the Linux platform, make sure you set the `BrokerOptions` to `OperatingSystems.Linux` as shown in the below code snippet: |
| 105 | + |
| 106 | +Reference the [Enable SSO in native Linux apps using MSAL Python](./linux-broker-py.md) for information of how to configure the project. |
| 107 | + |
| 108 | +### **Python Dependencies** |
| 109 | + |
| 110 | +To use the broker, you will need to install the broker-related packages in addition to the core MSAL from PyPI: |
| 111 | + |
| 112 | +```python |
| 113 | +pip install msal[broker]>=1.31,<2 |
| 114 | +pip install pymsalruntime |
| 115 | +``` |
| 116 | + |
| 117 | +### Run the Sample App |
| 118 | + |
| 119 | +Once configured, you can call `acquire_token_interactive` to acquire a token. Save the following as `wsl_broker.py`: |
| 120 | + |
| 121 | +```python |
| 122 | +import sys # For simplicity, we'll read config file from 1st CLI param sys.argv[1] |
| 123 | +import json |
| 124 | +import logging |
| 125 | +import requests |
| 126 | +import msal |
| 127 | + |
| 128 | +# Optional logging |
| 129 | +# logging.basicConfig(level=logging.DEBUG) |
| 130 | + |
| 131 | +var_authority = "https://login.microsoftonline.com/common" |
| 132 | +var_client_id = " your-client-id-here" # Replace with your app's client ID |
| 133 | +var_username = "your-username-here" # Replace with your username, e.g., " |
| 134 | +var_scope = ["User.ReadBasic.All"] |
| 135 | + |
| 136 | +# Create a preferably long-lived app instance which maintains a token cache (Default cache is in memory only). |
| 137 | +app = msal.PublicClientApplication( |
| 138 | + var_client_id, |
| 139 | + authority=var_authority, |
| 140 | + enable_broker_on_windows=True, |
| 141 | + enable_broker_on_wsl=True |
| 142 | + ) |
| 143 | + |
| 144 | +# The pattern to acquire a token looks like this. |
| 145 | +result = None |
| 146 | + |
| 147 | +# Firstly, check the cache to see if this end user has signed in before |
| 148 | +accounts = app.get_accounts(username=var_username) |
| 149 | +if accounts: |
| 150 | + logging.info("Account(s) exists in cache, probably with token too. Let's try.") |
| 151 | + result = app.acquire_token_silent(var_scope, account=accounts[0]) |
| 152 | + |
| 153 | +if not result: |
| 154 | + logging.info("No suitable token exists in cache. Let's get a new one from AAD.") |
| 155 | + |
| 156 | + result = app.acquire_token_interactive(var_scope,parent_window_handle=app.CONSOLE_WINDOW_HANDLE) |
| 157 | + |
| 158 | +if "access_token" in result: |
| 159 | + print("Access token is: %s" % result['access_token']) |
| 160 | + |
| 161 | +else: |
| 162 | + print(result.get("error")) |
| 163 | + print(result.get("error_description")) |
| 164 | + print(result.get("correlation_id")) # You may need this when reporting a bug |
| 165 | + if 65001 in result.get("error_codes", []): # Not mean to be coded programatically, but... |
| 166 | + # AAD requires user consent for U/P flow |
| 167 | + print("Visit this to consent:", app.get_authorization_request_url(config["scope"])) |
| 168 | +``` |
| 169 | + |
| 170 | +### Run the Sample |
| 171 | + |
| 172 | +Run the sample app using the following command: |
| 173 | + |
| 174 | +```bash |
| 175 | +python wsl_broker.py |
| 176 | +``` |
| 177 | + |
| 178 | +You should see a prompt to: |
| 179 | + |
| 180 | +- enter your username/credentials |
| 181 | +- enter your keyring password |
| 182 | +- then the app will acquire a token and print it to the console |
0 commit comments