user2154589
user2154589

Reputation: 49

Access AD access users OneDrive through Microsoft Graph API error "Unable to retrieve user's mysite URL"

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

Answers (1)

Sridevi
Sridevi

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:

enter image description here

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:

enter image description here

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

enter image description here

Now, I granted below API permissions of Delegated type in that application:

enter image description here

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:

enter image description here

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:

enter image description here

Upvotes: 0

Related Questions