Get Azure AD tokens for users by using MSAL

You can use the Microsoft Authentication Library (MSAL) to acquire Azure Active Directory (Azure AD) access tokens programatically. This article describes basic usage of the MSAL library and required user inputs, with Python examples.

Note

MSAL replaces the Azure Active Directory Authentication Library (ADAL). All Microsoft support and development for ADAL, including security fixes, ended on June 30, 2022. See Migrate applications to the Microsoft Authentication Library (MSAL).

Tip

You might want to try using the Azure CLI instead of the MSAL to get Azure AD tokens for users, as using the Azure CLI involves fewer steps. See Get Azure AD tokens for users by using the Azure CLI.

You can also define a service principal in Azure Active Directory and get an Azure AD access token for the service principal rather than for a user. See Get Azure AD tokens for service principals.

Configure an app in Azure portal

Register an application with the Azure AD endpoint in the Azure portal. Alternatively, you can use an Azure AD app that is already registered. For more information, see Register an app by using the Azure portal.

  1. Sign in to the Azure portal.

    Note

    The portal to use is different depending on whether your Azure AD application runs in the Azure public cloud or in a national or sovereign cloud. For more information, see National clouds.

  2. If you have access to multiple tenants, subscriptions, or directories, click the Directories + subscriptions (directory with filter) icon in the top menu to switch to the directory in which you want to register the application.

  3. Search for and select Azure Active Directory.

  4. Within Manage, select App registrations > New registration.

  5. For Name, enter a name for the application.

  6. In the Supported account types section, select Accounts in this organizational directory only (Single tenant).

  7. In the Redirect URI (optional) section, for Select a platform, select Public client/native (mobile & desktop) and enter a redirect URI. In the following example, the redirect URI value is http://localhost.

    Register app

  8. Click Register.

  9. On the application page’s Overview page, in the Essentials section, copy the following values:

    • Application (client) ID
    • Directory (tenant) ID
    • In Redirect URIs, the public client redirect URI that you entered earlier in this procedure.

    Azure registered app overview

  10. Add AzureDatabricks to the required permissions of the registered application. You must be an admin user to perform this step. If you encounter a permissions-related issue while you perform this action, contact your administrator for help.

    1. On the application page’s Overview page, on the Get Started tab, click View API permissions.

      Azure registered app settings

    2. Click Add a permission.

      Add required permissions to app

    3. In the Request API permissions pane, click the APIs my organization uses tab, search for AzureDatabricks, and then select it.

      Add AzureDatabricks API permission

    4. Enable the user_impersonation check box, and then click Add permissions.

      Azure app delegated permissions

    5. Click Grant admin consent for ### and then Yes. To perform this action, you must be an admin user or have the privilege to grant consent to the application. If you do not see Grant admin consent for ###, or if you skip this action, you must use the Authorization code flow (interactive) the first time you use the application to provide consent. After that, you can use the Username-password flow (programmatic) method.

      Add additional users and groups to app permissions

You can add additional users to the application. For more information, see Assign a user account to an enterprise application for Azure portal instructions or Assign users and groups to an application in Azure Active Directory for PowerShell instructions. A user will not be able to obtain a token without required permissions.

Get an Azure AD access token

To get an Azure AD access token, you can use either the:

You must use the authorization code flow (interactive) to get the Azure AD access token if:

  • Two factor authentication is enabled in Azure AD.
  • Federated authentication is enabled in Azure AD.
  • You are not granted consent to the registered application during application registration.

If you have the authority to sign in with a username and password, you can use the username-password flow (programmatic) to obtain an Azure AD access token.

Authorization code flow (interactive)

There are two steps to acquire an Azure AD access token using the authorization code flow.

  1. Request an authorization code, which launches a browser window and asks for Azure user login. The authorization code is returned after the user successfully logs in.
  2. Use the authorization code to acquire the Azure AD access token. Depending on the approach that you use, a refresh token can also be returned at the same time and can be used to refresh the Azure AD access token.

One approach to complete these two steps is to use your web browser and curl. To do this, you use your web browser to get the authorization code, and then you use the authorization code and curl to get the Azure AD access token. This approach does not provide a refresh token.

Another approach is to use the MSAL Python library. To do this, you run a single script that uses your web browser to get the authorization code and then uses the authorization code to get both an access and refresh token.

Both of these approaches assume that you are already signed in to Azure. If you are not signed in, your web browser will prompt you to do so.

Get Azure AD tokens by using a web browser and curl

  1. Gather the following information:

    Parameter Description
    Tenant ID The Directory (tenant) ID for the application registered in Azure AD in Configure an app in Azure portal.
    Client ID The Application (client) ID for the application registered in Azure AD.
    Redirect URI The appropriate Redirect URIs for the application registered in Azure AD (for example, http://localhost). The authentication responses are sent to this URI with the authorization code included.
  2. Get the authorization code by using your web browser to browse to the following URL. Replace the fields in the following URL example accordingly. Note that the URL must be sent as a single line; line breaks have been added to the following URL for readability. For more information, see Request an authorization code.

    https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize?client_id=<client-id>
    &response_type=code
    &redirect_uri=<redirect-uri>
    &response_mode=query
    &scope=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d%2F.default
    &state=<state>
    

    Replace:

    • <tenant-id> with the registered application’s tenant ID.
    • <client-id> with the registered application’s client ID.
    • <redirect-uri> with the registered application’s redirect URI. This URI must be in URL-encoded (percent-encoded) format. For example, http://localhost is http%3A%2F%2Flocalhost.
    • <state> with a random number or some encoded information. To help check for the integrity of information exchange, this state value should match the one that is in the returned URL later in this procedure.

    Do not change the value of the scope parameter. It represents the programmatic ID for Azure Databricks (2ff814a6-3304-4ab8-85cb-cd0e6f879c1d) along with the default scope (/.default, URL-encoded as %2f.default).

    For example:

    https://login.microsoftonline.com/a1bc2d34-5e67-8f89-01ab-c2345d6c78de/oauth2/v2.0/authorize?client_id=12a34b56-789c-0d12-e3fa-b456789c0123
    &response_type=code
    &redirect_uri=http%3A%2F%2Flocalhost
    &response_mode=query
    &scope=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d%2F.default
    &state=12345
    
  3. Paste the URL as a single line into your web browser and, if prompted, sign in to Azure.

    HTTP request URL

  4. The authorization code is in the code field in the returned URL. Save the authorization code in a secure location. Also, check to make sure that the value of the state field matches the one that you provided earlier in this procedure.

    Authorization code URL

    The full returned URL will look something like this (with the full code field value shortened to 0.ASkAIj...RxgFhSAA here for brevity):

    http://localhost/?code=0.ASkAIj...RxgFhSAA&state=12345&session_state=c44574d5-38ba-4f93-b2a3-a830db8e8cdf
    
  5. Use the authorization code along with curl to get the Azure AD access token.

    curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
    https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token \
    -d 'client_id=<client-id>' \
    -d 'scope=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d%2F.default' \
    -d 'code=<authorization-code>' \
    -d 'redirect_uri=<redirect-uri>' \
    -d 'grant_type=authorization_code' \
    -d 'state=<state>'
    

    Replace:

    • <tenant-id> with the registered application’s tenant ID.
    • <client-id> with the registered application’s client ID.
    • <authorization-code> with your authorization code.
    • <redirect-uri> with the registered application’s redirect URI. This URI must be in URL-encoded (percent-endoded) format. For example, http://localhost is http%3A%2F%2Flocalhost.
    • <state> with a random number or some encoded information. To help check for the integrity of information exchange, this state value should match the one that is in the response payload later in this procedure.

    Do not change the value of the scope parameter. It represents the programmatic ID for Azure Databricks (2ff814a6-3304-4ab8-85cb-cd0e6f879c1d) along with the default scope (/.default, URL-encoded as %2f.default).

    For example:

    curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
    https://login.microsoftonline.com/a1bc2d34-5e67-8f89-01ab-c2345d6c78de/oauth2/v2.0/token \
    -d 'client_id=12a34b56-789c-0d12-e3fa-b456789c0123' \
    -d 'scope=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d%2F.default' \
    -d 'code=0.ASkAIj...RxgFhSAA' \
    -d 'redirect_uri=http%3A%2F%2Flocalhost' \
    -d 'grant_type=authorization_code' \
    -d 'state=12345'
    

    The Azure AD token is in the access_token value within the result of the call. Be sure to check that the state value matches the one that you provided earlier in this procedure.

Get Azure AD tokens by using the MSAL Python library

  1. Gather the following information:

    Parameter Description
    Tenant ID The Directory (tenant) ID for the application registered in Azure AD in Configure an app in Azure portal.
    Client ID The Application (client) ID for the application registered in Azure AD.

    This procedure assumes that you have set http://localhost as the Redirect URI for the application registered in Azure AD.

  2. Install the MSAL Python SDK on your local machine by running pip install msal.

  3. Save the following code as get-tokens.py on your local machine.

    # Given the client ID and tenant ID for an app registered in Azure,
    # provide an Azure AD access token and a refresh token.
    
    # If the caller is not already signed in to Azure, the caller's
    # web browser will prompt the caller to sign in first.
    
    # pip install msal
    from msal import PublicClientApplication
    import sys
    
    # You can hard-code the registered app's client ID and tenant ID here,
    # or you can provide them as command-line arguments to this script.
    client_id = '<client-id>'
    tenant_id = '<tenant-id>'
    
    # Do not modify this variable. It represents the programmatic ID for
    # Azure Databricks along with the default scope of '/.default'.
    scopes = [ '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d/.default' ]
    
    # Check for too few or too many command-line arguments.
    if (len(sys.argv) > 1) and (len(sys.argv) != 3):
      print("Usage: get-tokens.py <client ID> <tenant ID>")
      exit(1)
    
    # If the registered app's client ID and tenant ID are provided as
    # command-line variables, set them here.
    if len(sys.argv) > 1:
      client_id = sys.argv[1]
      tenant_id = sys.argv[2]
    
    app = PublicClientApplication(
      client_id = client_id,
      authority = "https://login.microsoftonline.com/" + tenant_id
    )
    
    acquire_tokens_result = app.acquire_token_interactive(
      scopes = scopes
    )
    
    if 'error' in acquire_tokens_result:
      print("Error: " + acquire_tokens_result['error'])
      print("Description: " + acquire_tokens_result['error_description'])
    else:
      print("Access token:\n")
      print(acquire_tokens_result['access_token'])
      print("\nRefresh token:\n")
      print(acquire_tokens_result['refresh_token'])
    
  4. Do one of the following:

    • In the preceding code, replace <client-id> with the registered application’s client ID and <tenant-id> with the registered application’s tenant ID, and then run the script, for example python get-tokens.py.
    • Provide the registered application’s client ID and the registered application’s tenant ID when you run the script, for example python get-tokens.py 12a34b56-789c-0d12-e3fa-b456789c0123 a1bc2d34-5e67-8f89-01ab-c2345d6c78de.
  5. If your web browser prompts you, sign in to Azure.

  6. The Azure AD access and refresh tokens are printed in the output.

Username-password flow (programmatic)

  1. If you have the authority to sign in with a username and password, gather the following information:

    Parameter Description
    Tenant ID The Directory (tenant) ID for the application registered in Azure AD in Configure an app in Azure portal.
    Client ID The Application (client) ID for the application registered in Azure AD.
    Username and password The username (that is, the email address when you log in to Azure portal) and password of the user in the tenant.

    This procedure assumes that you have set http://localhost as the Redirect URI for the application registered in Azure AD.

  2. Install the MSAL Python SDK on your local machine by running pip install msal.

  3. Save the following code as get-tokens-for-user.py on your local machine.

    # Given the client ID and tenant ID for an app registered in Azure,
    # along with an Azure username and password,
    # provide an Azure AD access token and a refresh token.
    
    # If the caller is not already signed in to Azure, the caller's
    # web browser will prompt the caller to sign in first.
    
    # pip install msal
    from msal import PublicClientApplication
    import sys
    
    # You can hard-code the registered app's client ID and tenant ID here,
    # along with the Azure username and password,
    # or you can provide them as command-line arguments to this script.
    client_id = '<client-id>'
    tenant_id = '<tenant-id>'
    username = '<username>'
    password = '<password>'
    
    # Do not modify this variable. It represents the programmatic ID for
    # Azure Databricks along with the default scope of '/.default'.
    scope = [ '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d/.default' ]
    
    # Check for too few or too many command-line arguments.
    if (len(sys.argv) > 1) and (len(sys.argv) != 5):
      print("Usage: get-tokens-for-user.py <client ID> <tenant ID> <username> <password>")
      exit(1)
    
    # If the registered app's client ID and tenant ID along with the
    # Azure username and password are provided as command-line variables,
    # set them here.
    if len(sys.argv) > 1:
      client_id = sys.argv[1]
      tenant_id = sys.argv[2]
      username = sys.argv[3]
      password = sys.argv[4]
    
    app = PublicClientApplication(
      client_id = client_id,
      authority = "https://login.microsoftonline.com/" + tenant_id
    )
    
    acquire_tokens_result = app.acquire_token_by_username_password(
      username = username,
      password = password,
      scopes = scope
    )
    
    if 'error' in acquire_tokens_result:
      print("Error: " + acquire_tokens_result['error'])
      print("Description: " + acquire_tokens_result['error_description'])
    else:
      print("Access token:\n")
      print(acquire_tokens_result['access_token'])
      print("\nRefresh token:\n")
      print(acquire_tokens_result['refresh_token'])
    
  4. Do one of the following:

    • In the preceding code, replace <client-id> with the registered application’s client ID, <tenant-id> with the registered application’s tenant ID, <username> with the username, and <password> with the password, and then run the script, for example python get-tokens-for-user.py.
    • Provide the registered application’s client ID, the registered application’s tenant ID, the username, and the password when you run the script, for example python get-tokens-for-user.py 12a34b56-789c-0d12-e3fa-b456789c0123 a1bc2d34-5e67-8f89-01ab-c2345d6c78de someone@example.com "MyPa55w&rd!". If a command-line argument contains special characters, you should surround it with quotes.
  5. The Azure AD access and refresh tokens are printed to your terminal.

Use an Azure AD access token to access the Databricks REST API

This section describes how to use an Azure AD access token to call the Databricks REST API. In the following examples, replace <access-token> with the Azure AD access token and <databricks-instance> with the per-workspace URL of your Azure Databricks deployment.

Python example

This example shows how to list the clusters in an Azure Databricks workspace.

import requests
import json

databricks_instance = '<databricks-instance>'
api_version = '/api/2.0'
api_command = '/clusters/list'
url = f"https://{databricks_instance}{api_version}{api_command}"
access_token = '<access-token>'

response = requests.get(
  url = url,
  headers = { 'Authorization': "Bearer " + access_token}
)

print(json.dumps(json.loads(response.text), indent = 2))

Note

If you are a non-admin user and want to log in as an admin user, you must provide the X-Databricks-Azure-Workspace-Resource-Id header in addition to the 'Authorization' : 'Bearer ' header and you must be in a Contributor or Owner role on the workspace resource in Azure. You construct the X-Databricks-Azure-Workspace-Resource-Id value as follows:

# ...

subscription = '<azure-subscription-id>'
resource_group = '<azure-resource-group-name>'
workspace = '<databricks-workspace-name-in-azure>'

db_resource_id = '/subscriptions/%s/resourcegroups/%s/providers/microsoft.databricks/workspaces/%s' % (
  subscription,
  resource_group,
  workspace
)

# ...

  headers = {
    'Authorization': "Bearer " + access_token,
    'X-Databricks-Azure-Workspace-Resource-Id': db_resource_id
  }

# ...

To get the subscription, resource, and workspace information in Azure, see Open resources. To open the target resource, you can search on the Azure Databricks service type and any other information in Azure that you know about the target Azure Databricks workspace.

curl example

curl -X GET \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
https://<databricks-instance>/api/2.0/clusters/list

Refresh an Azure AD access token

If you get a refresh token along with your Azure AD access token, you can use the refresh token to obtain a new token. By default, the lifetime of Azure AD access tokens is a random time period between 60 and 90 minutes (75 minutes on average). You can configure the lifetime of Azure AD access tokens by using the methods in Configurable token lifetimes in Azure Active Directory.

The following example shows how to use the MSAL Python library along with a refresh token to obtain a new token.

  1. Save the following code as refresh-tokens.py on your local machine.

    # Given the client ID and tenant ID for an app registered in Azure,
    # along with a refresh token, provide a new Azure AD access token and
    # refresh token.
    
    # If the caller is not already signed in to Azure, the caller's
    # web browser will prompt the caller to sign in first.
    
    # pip install msal
    from msal import PublicClientApplication
    import sys
    
    # You can hard-code the registered app's client ID, tenant ID,
    # and refresh token here, or you can provide them as command-line
    # arguments to this script.
    client_id = '<client-id>'
    tenant_id = '<refresh-token'
    refresh_token = '<refresh-token>'
    
    # Do not modify this variable. It represents the programmatic ID for
    # Azure Databricks along with the default scope of '.default'.
    scope = [ '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d/.default' ]
    
    # Check for too few or too many command-line arguments.
    if (len(sys.argv) > 1) and (len(sys.argv) != 4):
      print("Usage: refresh-tokens.py <client ID> <tenant ID> <refresh token>")
      exit(1)
    
    # If the registered app's client ID, tenant ID, and refresh token are
    # provided as command-line variables, set them here.
    if len(sys.argv) > 1:
      client_id = sys.argv[1]
      tenant_id = sys.argv[2]
      refresh_token = sys.argv[3]
    
    app = PublicClientApplication(
      client_id = client_id,
      authority = "https://login.microsoftonline.com/" + tenant_id
    )
    
    acquire_tokens_result = app.acquire_token_by_refresh_token(
      refresh_token = refresh_token,
      scopes = scope
    )
    
    if 'error' in acquire_tokens_result:
      print("Error: " + acquire_tokens_result['error'])
      print("Description: " + acquire_tokens_result['error_description'])
    else:
      print("\nNew access token:\n")
      print(acquire_tokens_result['access_token'])
      print("\nNew refresh token:\n")
      print(acquire_tokens_result['refresh_token'])
    
  2. Do one of the following:

    • In the preceding code, replace <client-id> with the registered application’s client ID, <tenant-id> with the registered application’s tenant ID, and <refresh-token> with the refresh token, and then run the script, for example python get-tokens-for-user.py.
    • Provide the registered application’s client ID, the registered application’s tenant ID, and the refresh token when you run the script, for example python refresh-tokens.py 12a34b56-789c-0d12-e3fa-b456789c0123 a1bc2d34-5e67-8f89-01ab-c2345d6c78de "0.ASkAIj...huE84ALg". If a command-line argument contains special characters, you should surround it in quotes.
  3. The new Azure AD access and refresh tokens are printed to your terminal.