最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

azure - OneDrive Picture Download using python msal fails with 401 Error "unauthenticated" - Stack Overflow

programmeradmin6浏览0评论

Trying to download my (personal) photos from OneDrive (want to backup them on my NAS)

Created an API Key in Azure Portal. Enterprise applications | All applications

Added "http://localhost" to redirect URL. Using a "Desktop Application" (so no client_secret allowed).

Added the following Rights to the API Key: application rights

    User.Read
    User.Export.All
    Files.ReadWrite.All

Using (python) MSAL library:

$ pip list | grep msal
msal                  1.32.0
msal-extensions       1.3.1

Using PublicClientApplication and "consumers" endpoint to create an app:

app = PublicClientApplication(
    app_id,
    authority=";)

Browser opens, I confirm, browser gets redirected to localhost:

Authentication completed. You can close this window now.

Creating a token with the following scopes:

scopes = ["User.Read", "User.Export.All", "Files.ReadWrite.All"]
result = app.acquire_token_interactive(scopes=scopes)

Token gets returned.

Using that token to Download Infos for the Files stored: request_url = '.0/me/drive/root:/Bilder/Eigene Aufnahmen:/children'

That works fine and returns json information for all files in this folder, e.g.: "@microsoft.graph.downloadUrl": ".aspx?UniqueId=bbadf7cd-c0d9-20c1-80bf-042d00000000&Translate=false&tempauth=v1e.eyJzaXRlaWQiOiI0OTgwMzNhOC00MWVjLTQ4Y2QtYTg2YS0xYjYwNjViMmUyMDUiLCJhcHBfZGlzcGxheW5hbWUiOiJQZXJzb25hbCBadWdyaWZmIGF1ZiBPbmVEcml2ZSIsImFwcGlkIjoiNmNhZTJhMmEtNzAwOS00ZDY2LWE5MjgtYmU1ZjQ[...]

When using this URL to download the Photo, i get:

{"error":{"code":"unauthenticated","message":"Unauthenticated"}}
401

HTTP error 401 and "unauthenticated" message ..

Can someone point me to a direction?

If retrieving information about the folders using the access token works fine, why does it return 401 when trying to download the content of the file?

Full script is here:

#!/usr/bin/python3

import requests
import json
from msal import PublicClientApplication

### config
app_id = '6cae2a2a-XXX'
authority = ''
scopes = ["User.Read", "User.Export.All", "Files.ReadWrite.All"]

### start main ###

### create app 
app = PublicClientApplication(app_id, authority=authority)

### get access token
result = app.acquire_token_interactive(scopes)

if "access_token" in result:
    print("Got access_token: " + result["access_token"])
else:
    print(result.get("error"))
    print(result.get("error_description"))
    print(result.get("correlation_id"))  # You may need this when reporting a bug
    exit()

### try to download with access_token
request_url = '.0/me/drive/root:/Bilder/Eigene Aufnahmen:/children'
headers = {"Content-Type": "application/x-www-form-urlencoded",
           "Authorization": "Bearer " + result["access_token"]
           }

response = requests.get(request_url, headers=headers)
print (response.text)
print (response.status_code)
print (json.dumps(response.json(), indent=3))

This works fine (listing all files) .. changing the URL to the Download URL of one of the files gives 401 error ..

As for the permissions the Application has:

$ az ad app permission list --id 6cae2a2a-7009-4d66-a928-XXX
[
  {
    "resourceAccess": [
      {
        "id": "863451e7-0667-486c-a5d6-d135439485f0",
        "type": "Scope"
      },
      {
        "id": "405a51b5-8d8d-430b-9842-8be4b0e9f324",
        "type": "Scope"
      },
      {
        "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
        "type": "Scope"
      }
    ],
    "resourceAppId": "00000003-0000-0000-c000-000000000000"
  }
]
$ az ad app permission list-grants --id 6cae2a2a-7009-4d66-a928-XXX
[
  {
    "clientId": "64facadb-8227-464e-aa21-XXX",
    "consentType": "AllPrincipals",
    "id": "28r6ZCeCTkaqIZfQJobl9BMQHNlpjqxEqXXX",
    "principalId": null,
    "resourceId": "d91c1013-8e69-44ac-abb8-8508276a8376",
    "scope": " Files.ReadWrite.All User.Export.All User.Read offline_access openid profile"
  }
]

Trying to download my (personal) photos from OneDrive (want to backup them on my NAS)

Created an API Key in Azure Portal. Enterprise applications | All applications

Added "http://localhost" to redirect URL. Using a "Desktop Application" (so no client_secret allowed).

Added the following Rights to the API Key: application rights

    User.Read
    User.Export.All
    Files.ReadWrite.All

Using (python) MSAL library:

$ pip list | grep msal
msal                  1.32.0
msal-extensions       1.3.1

Using PublicClientApplication and "consumers" endpoint to create an app:

app = PublicClientApplication(
    app_id,
    authority="https://login.microsoftonline/consumers")

Browser opens, I confirm, browser gets redirected to localhost:

Authentication completed. You can close this window now.

Creating a token with the following scopes:

scopes = ["User.Read", "User.Export.All", "Files.ReadWrite.All"]
result = app.acquire_token_interactive(scopes=scopes)

Token gets returned.

Using that token to Download Infos for the Files stored: request_url = 'https://graph.microsoft/v1.0/me/drive/root:/Bilder/Eigene Aufnahmen:/children'

That works fine and returns json information for all files in this folder, e.g.: "@microsoft.graph.downloadUrl": "https://my.microsoftpersonalcontent/personal/bfc1c0d9bbadf7cd/_layouts/15/download.aspx?UniqueId=bbadf7cd-c0d9-20c1-80bf-042d00000000&Translate=false&tempauth=v1e.eyJzaXRlaWQiOiI0OTgwMzNhOC00MWVjLTQ4Y2QtYTg2YS0xYjYwNjViMmUyMDUiLCJhcHBfZGlzcGxheW5hbWUiOiJQZXJzb25hbCBadWdyaWZmIGF1ZiBPbmVEcml2ZSIsImFwcGlkIjoiNmNhZTJhMmEtNzAwOS00ZDY2LWE5MjgtYmU1ZjQ[...]

When using this URL to download the Photo, i get:

{"error":{"code":"unauthenticated","message":"Unauthenticated"}}
401

HTTP error 401 and "unauthenticated" message ..

Can someone point me to a direction?

If retrieving information about the folders using the access token works fine, why does it return 401 when trying to download the content of the file?

Full script is here:

#!/usr/bin/python3

import requests
import json
from msal import PublicClientApplication

### config
app_id = '6cae2a2a-XXX'
authority = 'https://login.microsoftonline/consumers'
scopes = ["User.Read", "User.Export.All", "Files.ReadWrite.All"]

### start main ###

### create app 
app = PublicClientApplication(app_id, authority=authority)

### get access token
result = app.acquire_token_interactive(scopes)

if "access_token" in result:
    print("Got access_token: " + result["access_token"])
else:
    print(result.get("error"))
    print(result.get("error_description"))
    print(result.get("correlation_id"))  # You may need this when reporting a bug
    exit()

### try to download with access_token
request_url = 'https://graph.microsoft/v1.0/me/drive/root:/Bilder/Eigene Aufnahmen:/children'
headers = {"Content-Type": "application/x-www-form-urlencoded",
           "Authorization": "Bearer " + result["access_token"]
           }

response = requests.get(request_url, headers=headers)
print (response.text)
print (response.status_code)
print (json.dumps(response.json(), indent=3))

This works fine (listing all files) .. changing the URL to the Download URL of one of the files gives 401 error ..

As for the permissions the Application has:

$ az ad app permission list --id 6cae2a2a-7009-4d66-a928-XXX
[
  {
    "resourceAccess": [
      {
        "id": "863451e7-0667-486c-a5d6-d135439485f0",
        "type": "Scope"
      },
      {
        "id": "405a51b5-8d8d-430b-9842-8be4b0e9f324",
        "type": "Scope"
      },
      {
        "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
        "type": "Scope"
      }
    ],
    "resourceAppId": "00000003-0000-0000-c000-000000000000"
  }
]
$ az ad app permission list-grants --id 6cae2a2a-7009-4d66-a928-XXX
[
  {
    "clientId": "64facadb-8227-464e-aa21-XXX",
    "consentType": "AllPrincipals",
    "id": "28r6ZCeCTkaqIZfQJobl9BMQHNlpjqxEqXXX",
    "principalId": null,
    "resourceId": "d91c1013-8e69-44ac-abb8-8508276a8376",
    "scope": " Files.ReadWrite.All User.Export.All User.Read offline_access openid profile"
  }
]
Share Improve this question edited Mar 26 at 17:13 Andare asked Mar 26 at 10:51 AndareAndare 32 bronze badges 6
  • Could you share the screenshot of your API permission blade and code which you are trying and edit the question? – Pratik Jadhav Commented Mar 26 at 10:56
  • Refer this Microsoft Community Blog and let me know it helps or not? – Pratik Jadhav Commented Mar 26 at 11:08
  • @PratikJadhav: Posted full script .. Screenshot of the rights of the API Key is in the original post. It's supposed to be a "delegated access" type of thing .. – Andare Commented Mar 26 at 16:49
  • Which Supported account type of application you registered? Could share the screenshot like this and edit the question? – Pratik Jadhav Commented Mar 27 at 4:35
  • Could you please confirm do you want to download the .png file from your OneDrive Personal account using download link? – Pratik Jadhav Commented Mar 27 at 5:51
 |  Show 1 more comment

1 Answer 1

Reset to default 0

To download the Picture from OneDrive Personal account using Python MSAL

Initially, I Registered Microsoft Entra ID Application with Supported Account type of Microsoft Personal Account Users only:

Configured Authentication tab with Mobile and desktop applications and Added Redirect_URI:

Added delegated type Files.ReadWrite.All API permission like below:

{"error":{"code":"unauthenticated","message":"Unauthenticated"}}

To resolve the error you are getting, Needs to use tempauth in Authorization.

import requests
import msal
import re

# Replace with your App Registration details
CLIENT_ID = "<APPLICATION_ID>"  # Azure App Registration Client ID
AUTHORITY = "https://login.microsoftonline/consumers"  # Use 'consumers' for personal accounts
SCOPES = ["Files.ReadWrite.All"]

# Initialize MSAL Public Client
app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY)

# Authenticate interactively (opens browser)
token_result = app.acquire_token_interactive(SCOPES)
if not token_result or "access_token" not in token_result:
    print("[!] Authentication failed.")
    exit()

access_token = token_result["access_token"]
headers = {"Authorization": f"Bearer {access_token}"}

# File name (from OneDrive root)
file_name = "<FILE-PATH>"

# Request URL to get file metadata
file_metadata_url = f"https://graph.microsoft/v1.0/me/drive/root:/{file_name}"

# Get file metadata
response = requests.get(file_metadata_url, headers=headers)
if response.status_code != 200:
    print(f"[!] Error getting file details: {response.json()}")
    exit()

# Extract download URL
file_metadata = response.json()
download_url = file_metadata.get("@microsoft.graph.downloadUrl")

if not download_url:
    print("[!] Download link not found.")
    exit()

print(f"Download URL: {download_url}")

# Extract 'tempauth' token from URL
tempauth_match = re.search(r"tempauth=([^&]+)", download_url)
if not tempauth_match:
    print("[!] Failed to extract 'tempauth' token.")
    exit()

tempauth_token = tempauth_match.group(1)

# Set new headers using 'tempauth' instead of Bearer token
download_headers = {"Authorization": f"Bearer {tempauth_token}"}

# Download file
download_response = requests.get(download_url, headers=download_headers)

if download_response.status_code == 200:
    with open(file_name, "wb") as file:
        file.write(download_response.content)
    print(f" File downloaded successfully: {file_name}")
else:
    print(f"[!] Error downloading file: {download_response.status_code}")
    print(download_response.text)


Grant the permission to application to access your OneDrive Personal Account:

Response:

Also, When I clicked that download URL:

发布评论

评论列表(0)

  1. 暂无评论