Troubleshoot Azure Active Directory access tokens

This article describes how to troubleshoot errors you may encounter when getting 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 an Azure AD 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:

import jwt
def decode_token(token):
  decoded = jwt.decode(token, verify=False)

  for key in decoded.keys():
     print key + ': ' + str(decoded[key])

If you want a full decoding (including signature verification) of the token, you can use the following code snippet:

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 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:
      # found the key that matching the kid in the token 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(cert_str, default_backend())
          public_key = cert_obj.public_key()

  return public_key

# decode the given Azure AD access token
def aad_access_token_decoder(access_token):
  header = jwt.get_unverified_header(access_token)
  public_key = get_jwt_publickey(header['kid'])
  # the value of the databricks_resource_id is as defined above
  # i.e., 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 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.