1. 程式人生 > >【Azure Developer】Python 獲取Micrisoft Graph API資源的Access Token, 並呼叫Microsoft Graph API servicePrincipals介面獲取應用ID

【Azure Developer】Python 獲取Micrisoft Graph API資源的Access Token, 並呼叫Microsoft Graph API servicePrincipals介面獲取應用ID

問題描述

在Azure開發中,我們時常面臨獲取Authorization問題,需要使用程式碼獲取到Access Token後,在呼叫對應的API,如servicePrincipals介面。 如果是直接呼叫AAD的 OAuth 2.0 介面,可以通過https://login.chinacloudapi.cn/{tenant}/oauth2/v2.0/token來獲取Token。操作步驟在博文《使用Postman獲取Azure AD中註冊應用程式的授權Token,及為Azure REST API設定Authorization》中有詳細描述。

 

而本次我們使用的是Python SDK (azure.common.credentials) 先獲取到Access Token,然後呼叫Micrisoft Graph API介面,獲取servicePrincipals資訊。

問題解決

1) 在生成Access Token之前,需要準備好tenant_id,client_id,client_secret三個引數(在通過Azure AAD中獲取)。獲取方式可見文末 附錄一

2) 然後呼叫credentials = ServicePrincipalCredentials(client_id, client_secret, tenant=tenant_id, resource='https://microsoftgraph.chinacloudapi.cn/', china='true')生成credentials物件。

3) 最後從credentials token中獲取到需要的access token

from azure.common.credentials import ServicePrincipalCredentials
 
tenant_id="954ddad8-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx"
client_id="596e55da-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx"
client_secret="__Fa5.J.xxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx"

credentials = ServicePrincipalCredentials(client_id, client_secret, tenant=tenant_id, resource='https://microsoftgraph.chinacloudapi.cn/', china='true')


access_token = credentials.token['access_token']

print(access_token)

獲取ServicePrincipals的資訊,呼叫介面:https://microsoftgraph.chinacloudapi.cn/v1.0/servicePrincipals

import urllib.request
import urllib
from flask import json


req = urllib.request.Request("https://microsoftgraph.chinacloudapi.cn/v1.0/servicePrincipals/%s" % (service_principaal_object_id))
req.add_header('Authorization', 'Bearer ' + access_token)
resp = urllib.request.urlopen(req)
content = resp.read()
content = json.loads(content)
#All content
print(content)

#print the application id 
print(content['appId'])

執行過程中錯誤

一:遇見 urllib.error.HTTPError: HTTP Error 401: Unauthorized 時,則要檢查ServicePrincipalCredentials中設定的resource是否與被訪問的API一致。

如時常出現Resource中設定為 https://graph.chinacloudapi.cn/。 而最後Request的URL Host為 https://microsoftgraph.chinacloudapi.cn/。 就會出現graph生成的Access Token無法訪問microsoftgraph的資源。

 

二:遇見 urllib.error.HTTPError: HTTP Error 403: Forbidden時,則要檢視當前使用的AAD應用的許可權是否足夠訪問ServicePrincipal資源。檢查方法如圖:

  

參考文件

1) Overview of Microsoft Graph:https://docs.microsoft.com/en-us/graph/overview?view=graph-rest-1.0

2) 使用Postman獲取Azure AD中註冊應用程式的授權Token,及為Azure REST API設定Authorization:https://www.cnblogs.com/lulight/p/14279338.html

3) 關於application和service principal的區別:https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals

4) Get servicePrincipal:https://docs.microsoft.com/en-us/graph/api/serviceprincipal-get?view=graph-rest-1.0&tabs=http

 

附錄一:在Azure AD中獲取應用的Client id,tenant id,client_secret

  • 訪問AAD應用註冊連結:https://portal.azure.cn/?l=zh-hans.zh-cn#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps
  • 選中Application,等頁面載入完成,頁面中的應用程式(客戶端)ID 和目錄(租戶)ID就是我們的Client ID, Tenant ID.

 

  • 獲取客戶端密碼[client_secret]
    • 在AAD應用頁面,進入“證書和密碼”頁面,點選“新客戶端密碼”按鈕,新增新的Secret(因密碼值只能在最開始建立時可見,所以必須在離開頁面前複製它

 

 

附錄二:完整程式碼及執行結果

from azure.common.credentials import ServicePrincipalCredentials
import urllib.request
import urllib
from flask import json

service_principaal_object_id="954ddad8-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx"

tenant_id="954ddad8-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx"
client_id="596e55da-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx"
client_secret="__Fa5.J.xxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx"

credentials = ServicePrincipalCredentials(client_id,client_secret, tenant=tenant_id,
                                             resource="https://microsoftgraph.chinacloudapi.cn/",china="true")
                                             
credentials = ServicePrincipalCredentials(client_id, client_secret, tenant=tenant_id, 
                                            resource='https://graph.chinacloudapi.cn/', china='true')


access_token = credentials.token['access_token']

print(access_token)


req = urllib.request.Request("https://microsoftgraph.chinacloudapi.cn/v1.0/servicePrincipals/%s" % (service_principaal_object_id))
req.add_header('Authorization', 'Bearer ' + access_token)
resp = urllib.request.urlopen(req)
content = resp.read()
content = json.loads(content)
#All content
print(content)

#print the application id 
print(content['appId'])

 

[