本文介绍如何排查获取 Microsoft Entra ID 访问令牌时可能会遇到的错误,以及如何验证访问令牌。
无法使用用户名和密码获取令牌
错误消息
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.
解决方案
- 如果未将 AzureDatabricks 资源添加到应用程序,请让管理员用户添加它。
- 使用 交互式方法 获取令牌。 该网页将指导你向应用程序授予权限。 或者,单击应用程序配置中所述的 “授予权限 ”按钮。 授予权限后,可以使用编程方法获取令牌。
重定向 URI 不匹配
错误消息
The reply URL specified in the request does not match the reply URLs configured for the application: '<application-id>'
解决方案
检查请求中的重定向 URI 是否与应用程序中的重定向 URI 匹配。
验证访问令牌
如果有Microsoft Entra ID 访问令牌,可以验证它是否包含正确的信息(请参阅 验证令牌)。
应验证以下字段是否与记录匹配:
- aud:Azure Databricks 资源 ID:
2ff814a6-3304-4ab8-85cb-cd0e6f879c1d
- iss:应为
https://sts.windows.net/<tenant-id>/
- tid:应是工作区的租户(可通过组织 ID 或工作区设备 ID 查找)
- nbf/exp:当前时间应介于
nbf
和exp
- unique_name:应是 Databricks 工作区中的用户,除非该用户是工作区设备资源的贡献者
使用来自 OIDC 终结点 的公共证书来验证令牌的签名。
下面是显示令牌有效负载的代码片段。 必须先使用pip install pyjwt
安装 PyJWT 库,然后使用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])}")
如果想要对令牌进行完整解码(包括签名验证),可以使用以下代码片段。 必须首先使用 pip install pyjwt
安装 PyJWT 库,并使用 pip install cryptography
安装加密库。 此外,请确保在以下代码中替换 <databricks-resource-id>
:
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])}")
还可以通过在线 JWT 解码器查看已解码的令牌(如果它们不敏感)。 联机解码器的示例包括 jwt.ms 和 jwt.io。