Microsoft图形Api Python

2024-05-18 18:57:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在python脚本上执行microsoft graph请求,如:"https://graph.microsoft.com/v1.0/me""https://graph.microsoft.com/v1.0/me/messages"等等

在使用此web界面https://developer.microsoft.com/fr-fr/graph/graph-explorer测试这些请求时,所有请求都有效

在我的脚本中,只有这个请求可以工作"https://graph.microsoft.com/v1.0/me",其他请求会出错

这是我的剧本:

import msal
import jwt
import json
import sys
import requests
from datetime import datetime
from msal_extensions import *
graphURI = 'https://graph.microsoft.com'
tenantID = 'my tenant id'
authority = 'https://login.microsoftonline.com/' + tenantID
clientID = 'my client id'
scope = ["email Files.ReadWrite.All", "Mail.Read", "Mail.Read.Shared", "Mail.ReadBasic", "Mail.ReadWrite", "Mail.ReadWrite.Shared Mail.Send Mail.Send.Shared MailboxSettings.Read MailboxSettings.ReadWrite openid profile Sites.ReadWrite.All User.Read User.ReadBasic.All"]
username = 'yourAADUsername' # i keep this one like this, i don't know what is my username
result = None
tokenExpiry = None
def msal_persistence(location, fallback_to_plaintext=False):
    if sys.platform.startswith('win'):
        return FilePersistenceWithDataProtection(location)
    if sys.platform.startswith('darwin'):
        return KeychainPersistence(location, "my_service_name", "my_account_name")
        return FilePersistence(location)
def msal_cache_accounts(clientID, authority):
# Accounts
    persistence = msal_persistence("token_cache.bin")
    print("Is this MSAL persistence cache encrypted?", persistence.is_encrypted)
    cache = PersistedTokenCache(persistence)
    app = msal.PublicClientApplication(
    client_id=clientID, authority=authority, token_cache=cache)
    accounts = app.get_accounts()
    print(accounts)
    return accounts
def msal_delegated_refresh(clientID, scope, authority, account):
    persistence = msal_persistence("token_cache.bin")
    cache = PersistedTokenCache(persistence)
    app = msal.PublicClientApplication(
    client_id=clientID, authority=authority, token_cache=cache)
    result = app.acquire_token_silent_with_error(
    scopes=scope, account=account)
    return result
def msal_delegated_refresh_force(clientID, scope, authority, account):
    persistence = msal_persistence("token_cache.bin")
    cache = PersistedTokenCache(persistence)
    app = msal.PublicClientApplication(
    client_id=clientID, authority=authority, token_cache=cache)
    result = app.acquire_token_silent_with_error(
    scopes=scope, account=account, force_refresh=True)
    return result
def msal_delegated_device_flow(clientID, scope, authority):
    print("Initiate Device Code Flow to get an AAD Access Token.")
    print("Open a browser window and paste in the URL below and then enter the Code. CTRL+C to cancel.")
    persistence = msal_persistence("token_cache.bin")
    cache = PersistedTokenCache(persistence)
    app = msal.PublicClientApplication(client_id=clientID, authority=authority, token_cache=cache)
    flow = app.initiate_device_flow(scopes=scope)
    if "user_code" not in flow:
        raise ValueError("Fail to create device flow. Err: %s" % json.dumps(flow, indent=4))
    print(flow["message"])
    sys.stdout.flush()
    result = app.acquire_token_by_device_flow(flow)
    return result
def msal_jwt_expiry(accessToken):
    decodedAccessToken = jwt.decode(accessToken, verify=False)
    accessTokenFormatted = json.dumps(decodedAccessToken, indent=2)
    # Token Expiry
    tokenExpiry = datetime.fromtimestamp(int(decodedAccessToken['exp']))
    print("Token Expires at: " + str(tokenExpiry))
    return tokenExpiry
def msgraph_request(resource, requestHeaders):
    # Request
    results = requests.get(resource, headers=requestHeaders).json()
    return results
accounts = msal_cache_accounts(clientID, authority)
if accounts:
    for account in accounts:
        if account['username'] == username:
            myAccount = account
            print("Found account in MSAL Cache: " + account['username'])
            print("Obtaining a new Access Token using the Refresh Token")
            result = msal_delegated_refresh(clientID, scope, authority, myAccount)
print(result)
if result is None:
    # Get a new Access Token using the Device Code Flow
    result = msal_delegated_device_flow(clientID, scope, authority)
    print(result)
else:
    if result["access_token"]:
        msal_jwt_expiry(result["access_token"])
    else:
        # Get a new Access Token using the Device Code Flow
        result = msal_delegated_device_flow(clientID, scope, authority)
if result["access_token"]:
    msal_jwt_expiry(result["access_token"])
    # Query AAD Users based on voice query using DisplayName
    print(graphURI + "/v1.0/me")

requestHeaders = {'Authorization': 'Bearer ' + result["access_token"],'Content-Type': 'application/json'}
queryResults = msgraph_request(graphURI + "/v1.0/me",requestHeaders)
print(json.dumps(queryResults, indent=2))

所以当我执行这个查询时:queryResults = msgraph_request(graphURI + "/v1.0/me",requestHeaders)

输出为:

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
  "businessPhones": [],
  "displayName": "Joe Coral",
  "givenName": "Joe",
  "jobTitle": null,
  "mail": null,
  "mobilePhone": null,
  "officeLocation": null,
  "preferredLanguage": "en",
  "surname": "Coral",
  "userPrincipalName": "joe-coral-hotmail.fr#EXT#@joecoralhotmail.onmicrosoft.com",
  "id": "82a2ef56-dbb7-45a4-bc9c-c533fd2c5908"
}

但是当我使用这个查询时:queryResults = msgraph_request(graphURI + "/v1.0/me/messages",requestHeaders)

输出为:

{
  "error": {
    "code": "ResourceNotFound",
    "message": "Resource could not be discovered.",
    "innerError": {
      "date": "2021-06-08T15:03:31",
      "request-id": "fa8dc282-0c8d-4be4-a195-4488c4f86e23",
      "client-request-id": "fa8dc282-0c8d-4be4-a195-4488c4f86e23"
    }
  }
}

在我的ADD应用程序中,我授予了所有权限:

PERMISSIONS


Tags: tokenidappcachereturnaccountresultflow
1条回答
网友
1楼 · 发布于 2024-05-18 18:57:26

根据/v1.0/me请求的结果,我可以看到该用户是一个个人Microsoft帐户,并且已作为来宾添加到此AAD租户中

当您使用此用户登录https://developer.microsoft.com/fr-fr/graph/graph-explorer时,它实际上将您的帐户视为个人Microsoft帐户,而不是来宾用户

这是因为Microsoft Graph Explorer使用common端点进行身份验证。(详情请参阅mypervious answer

但是在您的代码中,我看到您放置了authority = 'https://login.microsoftonline.com/' + tenantID,这意味着它会将您的帐户视为此租户中的来宾用户

在这种情况下,当您调用/v1.0/me/messages时,它将尝试从Exchange Online中托管的O365邮箱获取邮件。但是来宾用户没有Exchange Online许可证,也不在Exchange Online中托管。这就是为什么会出现ResourceNotFound错误

因此,根据您的描述,我认为您正在尝试以个人Microsoft帐户而不是来宾用户的身份为用户获取消息

请将authority = 'https://login.microsoftonline.com/' + tenantID修改为authority = 'https://login.microsoftonline.com/common'。这应该可以解决问题

相关问题 更多 >

    热门问题