Azure 对 API 端点的请求在获得访问令牌后返回 401 Unauthorized

问题描述 投票:0回答:1

我们有一个 Python 代码试图查询部署在 Microsoft Azure 上的 API。该代码首先使用

azure-identity
库从 API 请求访问令牌,然后在请求的
Authorization
标头中发送令牌,如下所示:

import requests
from azure.identity import ClientSecretCredential

TENANT_ID = 'my-tenant-id'
CLIENT_ID = 'my-client-id'
CLIENT_SECRET = "my_client-secret"
SCOPES = ['api://my-client-id/.default']

identity_client = ClientSecretCredential(tenant_id=TENANT_ID,
                                         client_id=CLIENT_ID,
                                         client_secret=CLIENT_SECRET,
                                        authority='https://login.microsoftonline.com')

access_token = identity_client.get_token(SCOPES[0])
#Request the API endpoint


json = {
    "function_name": "function_name",
    "param1": "param1_value",
    "param2": "param2_value",
}

headers = {
    "Authorization": f"Bearer {access_token.token}",
    "Content-Type": "application/json"
}
response = requests.get('https://myapi.whatever/myendpoint',
                        json=json, headers=headers)

if response.status_code == 200:
    print(response.json()["result"])
else:
    print(response)

但是,我们也获得了一个访问令牌(在

jwt.io
上具有有效签名);我们在查询端点时收到以下错误/响应:

{'_content': b'missing_claim',
 '_content_consumed': True,
 '_next': None,
 'status_code': 401,
 'headers': {'Date': 'Fri, 12 May 2023 15:25:27 GMT', 'Content-Type': 'text/plain', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Request-Context': 'appId=cid-v1:752b04bc-08aa-4002-a618-d3e7be07a371', 'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'sameorigin', 'X-Permitted-Cross-Domain-Policies': 'none', 'Referrer-Policy': 'no-referrer'},
 'raw': <urllib3.response.HTTPResponse at 0x2967109e3a0>,
 'url': 'https://myapi.whatever/myendpoint',
 'encoding': 'ISO-8859-1',
 'history': [],
 'reason': 'Unauthorized',
 'cookies': <RequestsCookieJar[]>,
 'elapsed': datetime.timedelta(microseconds=306335),
 'request': <PreparedRequest [GET]>,
 'connection': <requests.adapters.HTTPAdapter at 0x296710856a0>}

我不确定是什么原因造成的,我们也正确配置了 API 的权限......任何人都知道是什么导致了这个错误以及如何解决它?谢谢。

另请注意,我们尝试使用其他库,例如

msal
例如:

app = msal.ConfidentialClientApplication(
    client_id=CLIENT_ID,
    client_credential=[CLIENT_SECRET],
    authority='https://login.microsoftonline.com/my-tenant-id',
    token_cache=cache,
)

result = None

result = app.acquire_token_silent(scopes=SCOPES, account=None)

if not result:
    print('Here')
    result = app.acquire_token_for_client(scopes=SCOPES)

但还是一样的错误...

python-3.x azure azure-active-directory access-token azure-identity
1个回答
0
投票

我同意 @Gaurav Mantri,如果您的服务主体没有调用 API 的权限,通常会出现错误

401 Unauthorized

为了确认,解码访问令牌并检查它是否具有

scp
API 权限声明。

如果您在

Expose an API
选项卡中添加范围,它会创建 delegated 权限,如下所示:

enter image description here

我使用 client credentials flow 像这样通过 Postman 生成访问令牌:

POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token

grant_type:client_credentials
client_id: <clientappID>
client_secret: <secret>
scope: api://<webapi_appID>/.default

回复:

enter image description here

当我使用上面的访问令牌调用 API 时,我也遇到了

401 Unauthorized
错误,如下所示:

GET https://myapiendpoint/weatherforecast

回复:

enter image description here

请注意,客户端凭证流不适用于delegated 权限。因此,

scp
声明将在生成的令牌中丢失 与客户端凭据流。

要解决错误,您必须使用 delegated 流,如授权代码流、交互流或用户名密码流等...

就我而言,我使用 授权码 流通过 Postman 生成访问令牌,如下所示:

POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token

grant_type:authorization_code
client_id: <clientappID>
client_secret: <secret>
scope: api://<webapi_appID>/.default
redirect_uri: https://jwt.ms
code: code

回复:

enter image description here

当我在 jwt.ms 中解码此令牌时,它具有

scp
声明,如下所示:

enter image description here

我可以像这样使用上面的访问令牌成功地进行API调用:

GET https://myapiendpoint/weatherforecast

回复:

enter image description here

您可以检查此SO线程以通过Python使用身份验证代码流生成访问令牌。

© www.soinside.com 2019 - 2024. All rights reserved.