acsone / acsone/msgraphfs

Forbidden error when client only has Site.Selected permission

Open
#9 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
10
Forks
4
PR merge metrics
No merged PRs in 30d

Description

For security reasons, it was decided that the app registration only receives Site.Selected as permission.
As a result, the _get_site_id() (and the functions below) return a Forbidden error.

Calling code:

storage_options = {
        "client_id": client_id,
        "tenant_id": tenant_id,
        "client_secret": client_secret,
    }
fs = fsspec.filesystem("msgd", **storage_options)
print(fs.ls(f"{site_name}/Documents/POC"))

httpx.HTTPStatusError: Client error '403 Forbidden' for url 'https://graph.microsoft.com/v1.0/sites?search=$site_name'

Full stack trace:

HTTP error 403: b'{"error":{"code":"accessDenied","message":"Access denied","innerError":{"date":"2026-01-27T14:54:28","request-id":"$request_id","client-request-id":"$client_request_id"}}}'
Traceback (most recent call last):
  File "/home/AD/$USER/projects/$project/src/collab/fs.py", line 47, in <module>
    main()
    ~~~~^^
  File "/home/AD/$USER/projects/$project/src/collab/fs.py", line 37, in main
    print(fs.ls(f"<site-name>/Documents/POC"))
          ~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/fsspec/asyn.py", line 118, in wrapper
    return sync(self.loop, func, *args, **kwargs)
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/fsspec/asyn.py", line 103, in sync
    raise return_result
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/fsspec/asyn.py", line 56, in _runner
    result[0] = await coro
                ^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 1796, in _ls
    return await drive_fs._ls(file_path, detail=detail, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 1793, in _ls
    return await super()._ls(file_path, detail=detail, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 761, in _ls
    url = await self._path_to_url_async(path, item_id=item_id, action="children")
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 1728, in _path_to_url_async
    await self._ensure_drive_id()
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 1686, in _ensure_drive_id
    site_id = await self._get_site_id()
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 1735, in _get_site_id
    response = await self._msgraph_get(url)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 573, in _msgraph_get
    return await self._call_msgraph("GET", url, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 562, in _call_msgraph
    return await _http_call_with_retry(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<4 lines>...
    )
    ^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 152, in wrapper
    raise e
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 144, in wrapper
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 183, in _http_call_with_retry
    raise e
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/msgraphfs/core.py", line 164, in _http_call_with_retry
    response.raise_for_status()
    ~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/home/AD/$USER/.conda/envs/$project/lib/python3.13/site-packages/httpx/_models.py", line 829, in raise_for_status
    raise HTTPStatusError(message, request=request, response=self)
httpx.HTTPStatusError: Client error '403 Forbidden' for url 'https://graph.microsoft.com/v1.0/sites?search=$site_name'

Possible solutions:

  • Allow us to pass site_id in storage_options
  • Use a host_name + site_name combination, call GET https://graph.microsoft.com/v1.0/sites/<host_name>:/sites/<site_name> and parse the result

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in msgraphfs/core.py at _get_site_id(), _ensure_drive_id(), and the storage_options handling. Compare accepting site_id with resolving a site through the host_name/site_name Graph endpoint, then verify that fs.ls works when the client has only Site.Selected permission.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, authorization, cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.