Application access
Require Entra sign-in for the bundled web UI, retain the user's identity when invoking the Foundry-hosted orchestrator, and verify that retrieval excludes documents the user cannot read. Passing one of these checks does not prove the others.
The sign-in recipe below uses shipped settings. Protected hosted retrieval has an integration boundary described in step 3; completing sign-in does not complete that integration.
Before you start
- A deployed bundled application, with the UI using
CHAT_BACKEND=hosted_agent. - An application registration owner or administrator who can configure a confidential web application, plus an administrator authorized to grant the required API consent. Azure subscription access alone does not grant these Entra permissions.
- Permission to edit the deployment's App Configuration settings and Key Vault secrets, and to redeploy the affected application. Use a connected operator host for private deployments. The UI runtime identity also needs access to resolve those Key Vault references; operator access does not grant runtime access.
- Two test users in the tenant and nonsensitive test documents: one document readable by both, and one restricted to user A. User B must have no inherited group, source or administrative access to the restricted document.
Keep the Entra Application (client) ID, Directory (tenant) ID, and user
Object IDs separate from URLs. HOSTED_AGENT_BASE_URL is the deployed
agent endpoint; HOSTED_AGENT_RESOURCE_SCOPE is its data-plane token scope
ending in /.default, not an endpoint or an ARM scope.
1. Configure UI sign-in
- In Microsoft Entra admin center → App registrations, select the registration for this UI, or register a single-tenant application. Record its client and tenant IDs. Do not create another registration just to change an existing application's access policy.
- Under Expose an API, use Application ID URI
api://<client-id>and add an enabled delegated scope nameduser_impersonation. The bundled callback requiresapi://<client-id>/user_impersonation; it does not accept a Graph-only token. - Under Authentication, configure the Web redirect URI for the actual
UI origin and callback. After loading the credentials and settings in
steps 4–5 and redeploying the UI, obtain the exact URI from its
authorization request (
redirect_uriin browser developer tools); register that value, including its path and any deployment prefix; an initial Entra redirect-mismatch error can occur until it is registered. Do not substitute the Foundry endpoint. Use HTTPS outside local development. - Under Certificates & secrets, create or rotate the confidential-client
credential. Put its value, not its secret ID, in Key Vault and use a
Key Vault reference for
OAUTH_AZURE_AD_CLIENT_SECRET. Do not paste it into command history, tickets or source control. -
Set the following runtime keys in the deployment's App Configuration store. Use label
agent-lz, preserving existing secret references:Key Value OAUTH_AZURE_AD_CLIENT_IDRegistration's client ID OAUTH_AZURE_AD_TENANT_IDDirectory tenant ID OAUTH_AZURE_AD_ENABLE_SINGLE_TENANTtrueOAUTH_AZURE_AD_CLIENT_SECRETKey Vault reference to the credential OAUTH_AZURE_AD_SCOPESapi://<client-id>/user_impersonation,openid,profile,offline_accessCHAINLIT_AUTH_SECRETKey Vault reference to a persistent session-signing secret ALLOW_ANONYMOUSfalseHOSTED_AGENT_AUTH_MODEuser_delegatedoffline_accessis required by the callback's refresh-token exchange. Do not addUser.Reador other Graph scopes to this scope list: the shipped callback explicitly rejects them. 6. Review API permissions with the tenant administrator. Grant consent for the exposed API scope and the downstream delegated permission required by the deployed Foundry data-plane resource. The code consumesHOSTED_AGENT_RESOURCE_SCOPE; it does not prescribe a universal API permission name. Confirm that resource's registration and permission rather than guessing a permission from the endpoint hostname. Use Microsoft's OBO guidance to configure downstream consent. Users must sign in again after consent changes.
Complete callback registration in the test environment before opening access. Never enable anonymous production access to discover a callback.
2. Limit application admission
In App Configuration, set ALLOWED_USER_PRINCIPALS to a comma-separated list
of tenant-id:object-id values for admitted users. For the first test, include
only user A. ALLOWED_USER_NAMES is an alternative comma-separated list of
sign-in names; the two lists are combined with OR, not AND.
Use canonical GUID formatting. Bare user object IDs are accepted for backwards
compatibility, but prefer tenant-qualified IDs for new entries.
Empty lists admit every successfully authenticated user. These are UI admission rules, not document ACLs or a replacement for Foundry permissions. The callback does not fetch Graph group membership; adding a group name to either list does not implement group-based admission.
Apply and reload settings deliberately:
- In App Configuration → Configuration explorer, edit only the intended keys and label. Record the previous nonsecret values and secret-reference targets for rollback.
- Check for competing process environment settings and component-specific or
unlabelled keys. The UI reads several labels and bootstraps OAuth settings
into process environment; editing one
agent-lzkey is not proof that it becomes the effective value. - Redeploy the UI through the existing deployment workflow so its process reloads configuration; require a new browser sign-in. These changes are not a hot-reload contract. If changing orchestrator settings, redeploy the Foundry-hosted agent through that workflow too, not a nonexistent orchestrator Container App. Verify the routed agent version after redeployment; an existing hosted session is not proof that a new configuration was loaded.
Runtime keys are not interchangeable with azd env deployment inputs.
Provisioning can rewrite template-managed settings: retain approved deployment
inputs and recheck effective values after provisioning. See
Configuration for ownership and environment boundaries.
3. Verify the retrieval identity boundary
The UI exchanges the user's API token on behalf of the user for the configured
Foundry data-plane scope. user_delegated is the default and refuses a missing
user token; it does not silently fall back to a service identity.
service_identity deliberately makes Foundry see the UI service as caller.
Do not use it to repair per-user authorization failures.
The hosted container does not receive the caller's Authorization header.
In the pinned orchestrator, AGENT_STRATEGY=mcp uses the platform-injected
x-agent-foundry-call-id for Toolbox calls and rejects missing or malformed
call context. It does not trust caller-supplied identity/group fields.
The other hosted-eligible strategies do not acquire this Toolbox passthrough
merely by selecting RETRIEVAL_BACKEND=foundry_iq.
This is not a turnkey protected-retrieval switch. The shipped generic MCP
client forwards call context but does not acquire a Toolbox bearer token.
Current Microsoft guidance uses the authenticated FoundryToolbox SDK
integration, which also forwards hosted call context. A developer must reconcile
the bundled MCP integration with that
hosted Toolbox contract
before treating it as a working protected-retrieval path. Changing only
AGENT_STRATEGY=mcp is not sufficient.
The extension path is to connect the Foundry IQ knowledge base through Toolbox using that supported SDK integration, the appropriate end-user connection and source permissions, then redeploy and run the tests below. Foundry identity propagation is only one link: the knowledge source must ingest or honor the relevant permission metadata, and retrieval must enforce it. Preview capabilities and source-specific limits still apply; consult knowledge-base retrieval permissions. Do not forward a browser bearer token or invent identity headers to bypass the hosted gateway. A custom integration must preserve the platform call context and enforce source authorization; see Agent tools.
Shared source is a different policy. Explicit
FOUNDRY_IQ_INGESTION_PERMISSION_OPTIONS=[] removes ingestion permission
metadata for the supported shared native Blob case; it is not an OBO fix.
The protected default is ["rbacScope"]. Use the
shared-source configuration rules only for a corpus
deliberately readable by every admitted caller. UI login does not turn that
corpus into per-user protected content.
4. Run an allow/deny test
Run the document tests after the authenticated Toolbox integration and source permissions are in place. Until then, a successful UI login is only a login test, not evidence of document protection.
Use separate browser profiles, new conversations and unique phrases that exist only in the test documents. Check retrieved sources and citations as well as the answer; a fluent refusal alone is not evidence that retrieval was filtered.
| Test | Expected outcome |
|---|---|
| Signed out, open UI | Sign-in required; no anonymous chat |
| A admitted, B absent from both admission lists | A signs in; B is denied by the UI |
| Add B to the principal list, reload UI, both sign in again | Both can open chat and invoke the hosted agent |
| Both ask for the shared test document | Both retrieve the permitted document |
| A asks for the restricted document | A retrieves its content and citation |
| B asks the same question in a new conversation | No restricted content, excerpt or citation is retrieved |
| B asks for the restricted document by its exact title or unique phrase | Still no restricted content or citation |
| B attempts to open A's conversation/history | No disclosure of A's conversation |
Record the user object IDs, effective auth mode, agent version, knowledge base, source permission assignments and correlation IDs, without tokens or secret values. Repeat after permission changes have propagated and the source has refreshed permission metadata as required. For an intentionally shared corpus, both users retrieving the same document is expected; it does not validate per-user trimming.
Recover safely
- Redirect mismatch: compare the request's
redirect_uriwith the registration's Web URI, including scheme, host and prefix. - UI consent or refresh-token failure: check API scopes, tenant, credential expiry and consent; sign out and back in after correction. Do not replace the API scope with Graph scopes.
- Foundry invocation denied: distinguish failed OBO consent from missing
data-plane access for the user. Confirm the deployed resource scope and
endpoint. Do not switch to
service_identityas a workaround. - Missing platform call context: invoke through the deployed Foundry endpoint and check the Toolbox strategy/connection. Do not fabricate the call ID or enable a manual group-filter fallback.
- Tool requests user consent: follow the service-generated consent flow for that user and resource, then retry. UI login consent and Toolbox per-user consent are different; administrator application consent does not grant document access.
- B retrieves restricted content: stop access to the affected corpus, inspect source ACL ingestion and retrieval enforcement, then repeat the two-user test. Restoring login alone does not remediate a disclosure.
To undo a configuration change, restore the recorded values/references and
redeploy the affected component. Keep ALLOW_ANONYMOUS=false and the delegated
identity boundary while investigating.