Sharepoint Requests (Fedauth cookie)

Hey,

does anyone managed to obtain a fedauth cookie for a publicly shared sharepoint link, i want to download the stuff behind it.
I´m getting a 403 when trying it without the fedauth cookie, which i stole from pythons request lib, but i dont know to obtain one for a publicly shared link and why i´m forced to even get one.
More info about fedauth: SharePoint authentication - SharePoint in Microsoft 365 | Microsoft Learn

here is my code:

sharepoint_download_link =
          doc_api_link
          |> Kernel.<>("?download=1")

        case sharepoint_download_link
             |> download_pdf() do
          {:ok, file_content} ->
            conn
            |> send_download({:binary, file_content},
              filename: "document.pdf",
              disposition: :inline,
              charset: "utf-8"
            )

          {:error, status_code, reason} ->
            conn
            |> put_status(status_code)
            |> json(%{message: reason})
        end

  def download_pdf(pdf_url) do
    headers =
      [
        # {"User-Agent", ~c"python-requests/2.32.2"},
        # {~c"Accept-Encoding", "gzip, deflate"},
        # {"Accept", "*/*"},
        # {"Connection", ~c"keep-alive"},
        {~c"Cookie",
         ~c"FedAuth="}
        # {}'accept': 'application/json;odata=verbose'
      ]

    case HTTPoison.get(pdf_url, headers, follow_redirect: true) do
      {:ok, %HTTPoison.Response{status_code: status_code, body: body}} ->
        case status_code do
          200 ->
            {:ok, body}

          _ ->
            Logger.error(
              "Error downloading PDF from SharePoint. Status code: #{status_code}, Body: #{body}"
            )

            {:error, status_code, body}
        end

      {:error, %HTTPoison.Error{reason: reason}} ->
        Logger.error("Error downloading PDF from SharePoint: #{reason}")
        {:error, "Error downloading PDF: #{reason}"}
    end
  end

Thx

same for tesla


  def download_pdf(pdf_url) do
    middleware = [
      {Tesla.Middleware.FollowRedirects, max_redirects: 5},
      {Tesla.Middleware.Headers,
       [
         {"Cookie",
          "FedAuth="}
       ]}
    ]

    client = Tesla.client(middleware)

    case Tesla.get(client, pdf_url) do
      {:ok, %Tesla.Env{status: status_code, body: body}} ->
        case status_code do
          200 ->
            {:ok, body}

          _ ->
            Logger.error(
              "Error downloading PDF from SharePoint. Status code: #{status_code}, Body: #{body}"
            )

            {:error, status_code, body}
        end

      {:error, reason} ->
        Logger.error("Error downloading PDF from SharePoint: #{inspect(reason)}")
        {:error, "Error downloading PDF: #{inspect(reason)}"}
    end
  end

Would the Microsoft Graph API file endpoint work for what you are trying to accomplish? It does require authentication but it can all be done using OAuth rather than messing around with cookies.

You might also check the SharePoint policy for the tenant you are attempting to download from, this thread has some info on how to make sure truly public/anonymous access is enabled.

@windexoriginal that would be too logical for microsoft, i guess they want to track you first hehe.

found the solution:
sharepoint redirects you for the first download url and gives you the fedauth cookie in the first response.
You have to take it and the actual download location and start a new request like this when redirected:

          302 ->
            pdf_url |> IO.inspect()
            parsed_uri = URI.parse(pdf_url)

            # get the path of the real download
            download_location =
              headers
              |> Enum.find(fn {header_name, _} -> header_name == "Location" end)
              |> elem(1)

            download_url =
              "#{parsed_uri.scheme}://#{parsed_uri.host}#{download_location}"

            fed_auth_cookie =
              headers
              |> Enum.find(fn {header_name, _} -> header_name == "Set-Cookie" end)
              |> elem(1)

            download_pdf(download_url, fed_auth_cookie)

i guess this behaviour is already baked in to the python request lib

1 Like