Skip to content

Forbidden error when client only has Site.Selected permission #9

@Hemario

Description

@Hemario

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions