Building a SharePoint Online Proxy Layer for Public-Facing Dashboards

A public dashboard needs data from SharePoint Online. The obvious solution is to call Microsoft Graph directly from JavaScript—but that immediately creates a bigger problem: where do the credentials go, and how much of the tenant should the browser understand?

The problem: a public browser is the wrong trust boundary

The browser should not know a tenant ID, client secret, internal site ID, list GUID, or SharePoint field names. Even when delegated authentication is possible, it is usually the wrong experience for a public directory or status dashboard.

The quirk: friendly SharePoint names are not dependable API identifiers

A site displayed as “Instructional Council” may be addressed by a path such as IC. A list displayed as “Office Directory” may contain internal names created years ago.

GET /proxy/sharepoint.php?site=IC&list=Meetings

The workaround: use a tiny allow-listed proxy

$sites = [
    'IC'     => ['siteId' => 'known-site-guid'],
    'EmpRes' => ['siteId' => 'another-site-guid']
];

$lists = ['Meetings', 'Documents', 'Offices-Services-Directory'];

$site = $_GET['site'] ?? '';
$list = $_GET['list'] ?? '';

if (!isset($sites[$site]) || !in_array($list, $lists, true)) {
    http_response_code(404);
    exit('Unknown SharePoint source');
}

This is intentionally not a generic pass-through. The caller cannot provide an arbitrary Graph URL or OData query. The server chooses the permitted site, list, fields, page size, and timeout.

{
  "items": [],
  "count": 0,
  "generatedAt": "2026-10-29T19:00:00Z"
}

The public page gets a predictable response. The proxy gets one place for authentication, caching, logging, validation, and safe error messages. That small layer turns an exposed integration into a maintainable one.

Leave a Comment

Your email address will not be published. Required fields are marked *