Skip to main content

Authentication

Overview

To embed the SDAC widget, the host application loads the widget shell through APIM and provides a widget access token for protected widget API calls. The widget handles session creation, ingestion proxying, chat, validation, and upstream service credentials after it loads.

The host application must:

  1. Request a widget access token server-side.
  2. Render SDAC page metadata for district, quarter, year, and user context.
  3. Load the widget script and pass the token to the widget bootstrap.

Do not pass APIM subscription keys to the browser. Do not call ingestion routes directly from the host page.

For testing and Replit-driven UI work, prefer the Admin UI Widget Testing page. The dashboard server can mint a widget-testing token and launch the widget without giving Replit OAuth client credentials. Shared Replit workspaces should receive the testing APIM subscription key, not the widget OAuth tenant, client secret, or scope values.

Get a Widget Token

The host application server should request the token with the OAuth client-credentials flow. Use the tenant, client ID, client secret, and scope values provided for the SDAC environment.

WIDGET_TOKEN=$(curl -s -X POST \
"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
--data-urlencode "client_id={CLIENT_ID}" \
--data-urlencode "client_secret={CLIENT_SECRET}" \
--data-urlencode "scope={SCOPE}" \
| jq -r '.access_token')

The token must include the configured widget/API audience and the access_as_application app role.

Load the Widget

A normal browser <script> tag cannot send custom Authorization headers. The widget script itself is public, but the token must be available to the widget bootstrap so the iframe can send Authorization: Bearer ... on protected /widget/api/... calls.

<script
src="https://dev-sdac-aitools-wkhc-apim.azure-api.net/widget/embed.js"
data-widget-token="{WIDGET_TOKEN}">
</script>

The existing ?widget_token={WIDGET_TOKEN} script URL form is also supported for compatibility. The token authorizes protected widget API actions, not the public widget shell. Do not put district, quarter, year, or user context in the token.

Page Metadata

The widget reads district and user context from metadata already rendered on the host page. Preferred markup:

<div
id="sdac-meta-data"
data-sdac='{
"districtId": "12345",
"districtName": "Maplewood Richmond Heights",
"quarter": "Q1",
"year": "2026",
"userId": "auditor-001",
"userName": "Alex Auditor",
"userEmail": "auditor@state.gov",
"userRole": "State Auditor"
}'>
</div>

The widget also supports legacy data-sdac-* attributes. See Widget Integration for the full metadata contract.

Expected Behavior

ConditionResult
Missing or invalid widget_tokenThe widget shell loads, but protected widget API calls return 401
Valid widget_token but missing page metadataThe widget loads, but cannot resolve report context
Valid widget_token and valid page metadataThe widget creates the SDAC session and handles the rest