Reputation: 49
I'm trying to access my sharepoint/onedrive files via the Microsoft Graph API. I have a sharepoint/onedrive account, and I have many API permissions set, including 'Files.readwrite.all' and 'Sites.readwrite.all'. I can see that this user does have files in an online onedrive, but I'm not able to query them. The queries are successfully when I use the graph explorer under the users account. I am using 'Application Permissions'. Any idea how to fix?
Here are some broad queries that work & don't work: graph.microsoft.com/v1.0/users Returns a list of users without issues.
graph.microsoft.com/v1.0/users/UPN-PLACEHOLDER Returns information about the specified user without issues.
graph.microsoft.com/v1.0/users/UPN-PLACEHOLDER/drive DOES NOT WORK - Error "Unable to retrieve user's mysite URL"
graph.microsoft.com/v1.0/users/UPN-PLACEHOLDER/drive/root DOES NOT WORK - Error "Unable to retrieve user's mysite URL"
This is the specific code
SCOPE = ["https://graph.microsoft.com/.default"]
CLIENT_SECRET =
TENENT_ID =
APPLICATION_CLIENT_ID =
AUTHORITY = "https://login.microsoftonline.com/" + TENENT_ID
KFM_USER_ID =
ENDPOINT = "https://graph.microsoft.com/v1.0/users/" + KFM_USER_ID # THIS DOES WORK
ENDPOINT = "https://graph.microsoft.com/v1.0/users/" + KFM_USER_ID + "/drive" # THIS ISN"T WORKING :(
import msal
app = msal.ConfidentialClientApplication(APPLICATION_CLIENT_ID, authority=AUTHORITY, client_credential=CLIENT_SECRET)
result = app.acquire_token_for_client(scopes=SCOPE)
graph_data = requests.get(
ENDPOINT,
headers={'Authorization': 'Bearer ' + result['access_token']},
).json()
Upvotes: 0
Views: 355
Reputation: 22552
As mentioned in this MS Doc,
If a user's OneDrive is not provisioned but the user has a license to use OneDrive, this request will automatically provision the user's drive, when using delegated authentication.
I registered one Azure AD application and granted API permissions as below:
When I ran your code in my environment for user having valid license but not yet provisioned, I got same error:
import requests
import msal
SCOPE = ["https://graph.microsoft.com/.default"]
CLIENT_SECRET = "secret"
TENENT_ID = "tenantId"
APPLICATION_CLIENT_ID = "appId"
AUTHORITY = "https://login.microsoftonline.com/" + TENENT_ID
KFM_USER_ID = "userId"
#ENDPOINT = "https://graph.microsoft.com/v1.0/users/" + KFM_USER_ID # THIS DOES WORK
ENDPOINT = "https://graph.microsoft.com/v1.0/users/" + KFM_USER_ID + "/drive" # THIS ISN"T WORKING :(
app = msal.ConfidentialClientApplication(APPLICATION_CLIENT_ID, authority=AUTHORITY, client_credential=CLIENT_SECRET)
result = app.acquire_token_for_client(scopes=SCOPE)
graph_data = requests.get(
ENDPOINT,
headers={'Authorization': 'Bearer ' + result['access_token']},
).json()
print(graph_data)
Response:
To resolve the error, you need to use delegated authentication like authorization code flow, username password flow, interactive flow etc... by granting
Delegated
permissions.
In my case, I used username password flow to acquire token for which below option should be enabled(wait for few minutes after enabling as there will be delay):
Now, I granted below API permissions of Delegated
type in that application:
When I ran below modified code with username password flow, I got response successfully:
import requests
import msal
SCOPE = ["https://graph.microsoft.com/.default"]
CLIENT_SECRET = "secret"
TENENT_ID = "tenantId"
APPLICATION_CLIENT_ID = "appId"
AUTHORITY = "https://login.microsoftonline.com/" + TENENT_ID
KFM_USER_ID = "demosriId"
USERNAME = "[email protected]"
PASSWORD = "xxxxxxxxxxx"
#ENDPOINT = "https://graph.microsoft.com/v1.0/users/" + KFM_USER_ID # THIS DOES WORK
ENDPOINT = "https://graph.microsoft.com/v1.0/users/" + KFM_USER_ID + "/drive"
app = msal.PublicClientApplication(APPLICATION_CLIENT_ID, authority=AUTHORITY)
result = app.acquire_token_by_username_password(scopes=SCOPE, username=USERNAME, password=PASSWORD)
graph_data = requests.get(
ENDPOINT,
headers={'Authorization': 'Bearer ' + result['access_token']},
).json()
print(graph_data)
Response:
As Graph Explorer involves user to sign in, it comes under delegated authentication that works with
Delegated
permissions. So, the above queries will work in it by automatically provisioning user's drive.
Once user's drive is provisioned, you can also run your code with client credentials flow again that gives you same response successfully like below:
import requests
import msal
SCOPE = ["https://graph.microsoft.com/.default"]
CLIENT_SECRET = "secret"
TENENT_ID = "tenantId"
APPLICATION_CLIENT_ID = "appId"
AUTHORITY = "https://login.microsoftonline.com/" + TENENT_ID
KFM_USER_ID = "userId"
#ENDPOINT = "https://graph.microsoft.com/v1.0/users/" + KFM_USER_ID # THIS DOES WORK
ENDPOINT = "https://graph.microsoft.com/v1.0/users/" + KFM_USER_ID + "/drive" # THIS ISN"T WORKING :(
app = msal.ConfidentialClientApplication(APPLICATION_CLIENT_ID, authority=AUTHORITY, client_credential=CLIENT_SECRET)
result = app.acquire_token_for_client(scopes=SCOPE)
graph_data = requests.get(
ENDPOINT,
headers={'Authorization': 'Bearer ' + result['access_token']},
).json()
print(graph_data)
Response:
Upvotes: 0