Troubleshoot Microsoft Entra ID (formerly Azure Active Directory) access tokens

This article describes how to troubleshoot errors you may encounter when getting Microsoft Entra ID (formerly Azure Active Directory) access tokens and how to validate access tokens.

Failed to get token using username and password

Error Message

The user or administrator has not consented to use the application with ID <client-id>.
Send an interactive authorization request for this user and resource.

Solution

  1. If the AzureDatabricks resource is not added to your application, ask an Admin user to add it.
  2. Use the interactive method to get the token. The web page will guide you to grant permissions to the application. Alternatively, click the Grant permissions button described in the application configuration. After permissions are granted, you can use the programmatic method to get the token.

Redirect URIs do not match

Error Message

The reply url specified in the request does not match the reply urls configured for the application: '<application-id>'

Solution

Check that the redirect URI in your request matches one of those in the application.

Validate an access token

When you have a Microsoft Entra ID access token, you can verify that it includes the correct information (see validate tokens).

You should verify that the following fields match the record:

  • aud: The Azure Databricks resource ID: 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d
  • iss: Should be https://sts.windows.net/<tenant-id>/
  • tid: Should be the tenant of the workspace (look this up either by org ID or workspace appliance ID)
  • nbf/exp: Current time should fall between nbf and exp
  • unique_name: Should be a user that exists in the Databricks workspace, unless the user is a contributor on the workspace appliance resource

Validate the signature of the token using the public certs from the OIDC endpoints.

Here is an code snippet that shows the payload of the token. You must first install the PyJWT library using pip install pyjwt and the cryptography library using pip install cryptography:

import jwt

def decode_token(token):
  algorithm = jwt.get_unverified_header(token)['alg']

  decoded = jwt.decode(
    token,
    algorithms = [algorithm],
    options = {"verify_signature": False}
  )

  for key in decoded.keys():
     print(f"{key}: {str(decoded[key])}")

If you want a full decoding (including signature verification) of the token, you can use the following code snippet. You must first install the PyJWT library using pip install pyjwt and the cryptography library using pip install cryptography. Also, make sure to replace <databricks-resource-id> in the following code:

import jwt
import requests
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend

PEMSTART = '-----BEGIN CERTIFICATE-----\n'
PEMEND = '\n-----END CERTIFICATE-----\n'

# Get the Microsoft Azure public key.
def get_public_key_for_token(kid):
  response = requests.get(
    'https://login.microsoftonline.com/common/.well-known/openid-configuration',
  ).json()

  jwt_uri = response['jwks_uri']
  response_keys = requests.get(jwt_uri).json()
  pubkeys = response_keys['keys']

  public_key = ''

  for key in pubkeys:
    # Find the key that matches the kid in the token's header.
      if key['kid'] == kid:
        # Construct the public key object.
        mspubkey = str(key['x5c'][0])
        cert_str = PEMSTART + mspubkey + PEMEND
        cert_obj = load_pem_x509_certificate(bytes(cert_str, 'ascii'), default_backend())
        public_key = cert_obj.public_key()

  return public_key

# Decode the given <ms-entra-id> token.
def aad_access_token_decoder(access_token):
  header = jwt.get_unverified_header(access_token)
  public_key = get_public_key_for_token(header['kid'])
  # The value of the databricks_resource_id is as defined previously,
  # for example, databricks_resource_id = "2ff814a6-3304-4ab8-85cb-cd0e6f879c1d"
  decoded = jwt.decode(
    access_token,
    key = public_key,
    algorithms = 'RS256',
    audience = '<databricks-resource-id>')

  for key in decoded.keys():
    print(f"{key}: {str(decoded[key])}")

Here is an example of the output from the above code snippet:

Azure registered app settings

You can also view the decoded token through online JWT decoders if they are not sensitive. Examples of online decoders are jwt.ms and jwt.io.