博客 / 詳情

返回

當郵箱開啓MFA後,azure使用OAuth2.0進行身份認證

背景

公司的郵箱服務器開啓MFA後,無法使用用户名、密碼登陸。需要使用其他身份認證方式。
https://docs.azure.cn/zh-cn/entra/identity-platform/v2-oauth-...

警告
Microsoft建議不要使用 ROPC 流;它與多重身份驗證 (MFA) 不兼容。 在大多數情況下,提供了更安全的替代方法,建議使用。 此流需要在應用程序中高度信任,並且存在在其他流中不存在的風險。 僅當更安全的流不可行時,才應使用此流。

基礎知識可以參考:https://segmentfault.com/a/1190000045134213

使用MS graph api進行身份認證

使用authorization code進行身份認證

生成authorization code

生成url地址。這裏我只填寫必填項,全部的選項可以參看官方:https://docs.azure.cn/zh-cn/entra/identity-platform/v2-oauth2...

authorize_url = f"https://login.partner.microsoftonline.cn/{tenant_id}/oauth2/v2.0/authorize?\
client_id={client_id}\
&response_type={response_type}\
&redirect_uri={redirect_uri}\
&response_mode={response_mode}\
&scope={scope}\
&state={state}"

在瀏覽器中打開上面的地址,地址會跳向在azure中配置好的地址:
配置轉發地址

  • 跳轉成功:頁面上會顯示一串字符串,從code=開始到&state=之間的就是authorization code
  • 跳轉失敗:直接複製地址欄的地址,從中截取authotization code

生成access token

拿到authroization code後,調用api獲取access token。全選項參看:https://docs.azure.cn/zh-cn/entra/identity-platform/v2-oauth2...

def Authentication():
    tenant_id = 
    client_id = 
    code = 
    redirect_uri = "http://localhost:8000"
    grant_type = "authorization_code"
    client_secret = 


    url = f'https://login.partner.microsoftonline.cn/{tenant_id}/oauth2/v2.0/token'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Host': 'login.partner.microsoftonline.cn',
    }
    datas = {
        "client_id": client_id,
        "scope": scope,
        "code": code,
        "redirect_uri": redirect_uri,
        "grant_type": grant_type,
        "client_secret": client_secret,
    }

    data = urllib.parse.urlencode(datas)
    Data = data.encode('ascii')
    # print(data)

    req = urllib.request.Request(url=url, data=Data, headers=headers, method="POST")
    # print(req)
    response = urllib.request.urlopen(req, context=context)
    # response = urllib.request.urlopen(req)
    responseJson = json.loads(response.read().decode("utf-8"))
    print(responseJson["access_token"])
    # print(responseJson["access_token"])
    return responseJson["access_token"]
# Authentication()

使用access token調用MS graph REST api

MS graph REST api可以做很多事情,包括所有的產品、所有的操作。這裏舉例列出郵件
列出郵件:https://learn.microsoft.com/zh-cn/graph/api/user-list-message...

  1. 找到郵件文件夾

    https://learn.microsoft.com/zh-cn/graph/api/user-list-mailfol...
  2. 找到子文件夾

    https://learn.microsoft.com/zh-cn/graph/api/mailfolder-list-c...
  3. 通過子文件夾id獲得郵件列表

    https://learn.microsoft.com/zh-cn/graph/api/user-list-message...
  4. 在第3步中使用OData對結果進行篩選

使用SDK進行身份認證

https://learn.microsoft.com/zh-cn/graph/sdks/national-clouds?...

使用OData對MS graph REST api的結果進行過濾

格式

不同的參數用$標記,用&隔開

https://microsoftgraph.chinacloudapi.cn:443/v1.0/me/mailFolders/{folderID}/messages?$search="from:adelev OR from:alexw@163.com OR from: allanD"&$select=subject,createdDateTime,body&$top=100

參數可選項

https://learn.microsoft.com/zh-cn/graph/query-parameters?tabs...

可以對這些郵件的屬性進行過濾 和 支持的運算符

https://learn.microsoft.com/zh-cn/exchange/policy-and-complia...

注意

  1. 參數中對結果的過濾不一定想我們想的那樣,比如説$filter不能對收件人進行篩選。然而我沒有找到官方整理的表格,所以只能自己試一試😂😂😂
  2. 在調用的時候可能需要對地址進行轉義。正常理解$ & =這些都需要轉義,但是實際操作中,python只需要對空格進行轉義

    • python中使用urllib.parse.quote(),而不是urllib.parse.quote_plus()進行轉義
    • 因為只需要對空格進行轉義,所以只需要將包括空格的一段用轉義函數包括起來。其他特殊字符不能包括起來,不然會是一個bad request
    • 示例轉義代碼

      select = "$select=subject,createdDateTime,body"
      search = f'$search="{urllib.parse.quote(f"(received>={queryStartDate} AND received<={endDate}) AND from:{emailAddress1} AND (to:{emailAddress2} OR to:{emailAddress3})")}"'
      
      api = f"/me/mailFolders/{folderID}/messages?{search}&{select}&$top=100"
      url = 'https://microsoftgraph.chinacloudapi.cn:443/v1.0' + api
    • 關於OData中字符的轉義,可以參看這篇:https://userapps.support.sap.com/sap/support/knowledge/en/281...

分頁

結果太多,可以使用OData(不同的參數支持的$top=數量不一樣)或者@odata.nextLink(在MS graph REST api中返回)
https://learn.microsoft.com/zh-cn/graph/paging?tabs=http#impl...

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.