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.
