简体   繁体   English

微软图形 Api Python

[英]Microsoft Graph Api Python

I'm trying to execute microsoft graph requests as: "https://graph.microsoft.com/v1.0/me" , "https://graph.microsoft.com/v1.0/me/messages" and so on, on my python script我正在尝试执行 microsoft graph 请求为: "https://graph.microsoft.com/v1.0/me""https://graph.microsoft.com/v1.0/me/messages"等等在我的 python 脚本上

While testing those requests using this web interface https://developer.microsoft.com/fr-fr/graph/graph-explorer , all requests worked在使用此 web 接口https://developer.microsoft.com/fr-fr/graph/graph-explorer测试这些请求时,所有请求都有效

On my script, only this request work "https://graph.microsoft.com/v1.0/me" , other requests i get errors在我的脚本上,只有这个请求有效"https://graph.microsoft.com/v1.0/me" ,其他请求我得到错误

Here is my script:这是我的脚本:

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))

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

the output is: output 是:

{
  "@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"
}

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

the output is: output 是:

{
  "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"
    }
  }
}

And on my application on ADD, i granted all permissions:在我的 ADD 申请中,我授予了所有权限:

权限

Based on your result of the /v1.0/me request, I can see that the user is a personal Microsoft account and has been added into this AAD tenant as a guest.根据您的/v1.0/me请求结果,我可以看到该用户是个人 Microsoft 帐户,并且已作为来宾添加到此 AAD 租户中。

When you sign into https://developer.microsoft.com/fr-fr/graph/graph-explorer with this user, it actually treats your account as a personal Microsoft account rather than a guest user.当您使用此用户登录https://developer.microsoft.com/fr-fr/graph/graph-explorer时,它实际上将您的帐户视为个人 Microsoft 帐户,而不是来宾用户。

This is because Microsoft Graph Explorer uses common endpoint for authentication.这是因为 Microsoft Graph Explorer 使用common终结点进行身份验证。 (See details from my pervious answer ) (请参阅我以前的答案中的详细信息)

But in your code, I see that you put authority = 'https://login.microsoftonline.com/' + tenantID , which means it will treats your account as a guest user in this tenant.但是在您的代码中,我看到您输入了authority = 'https://login.microsoftonline.com/' + tenantID ,这意味着它将您的帐户视为该租户中的来宾用户。

In this case, when you call /v1.0/me/messages , it will try to get messages from your O365 mailbox hosted in Exchange Online.在这种情况下,当您调用/v1.0/me/messages时,它会尝试从 Exchange Online 中托管的 O365 邮箱中获取消息。 But the guest user doesn't have Exchange Online license and it's not hosted in Exchange Online.但来宾用户没有 Exchange Online 许可证,也没有托管在 Exchange Online 中。 That is why you get ResourceNotFound error.这就是您收到ResourceNotFound错误的原因。

Therefore, based on your description, I think you are trying to get messages for the user as a personal Microsoft account rather than a guest user.因此,根据您的描述,我认为您正试图以个人 Microsoft 帐户而不是来宾用户的身份为用户获取消息。

Please modify authority = 'https://login.microsoftonline.com/' + tenantID to authority = 'https://login.microsoftonline.com/common' .请修改authority = 'https://login.microsoftonline.com/' + tenantIDauthority = 'https://login.microsoftonline.com/common' This should resolve the issue.这应该可以解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM