Authentication
How callers get tokens for the Dispatcher - connector apps with client credentials, and people through REFRACT Lifecycle or a testing app - and which callers the Dispatcher accepts.
The Dispatcher accepts two OAuth 2.0 flows. In both, the token is issued for the "REFRACT Dispatcher API" app registration, and the caller is a different app registration: nobody signs in as "REFRACT Dispatcher API". Both pass the same token validation. After it, a signed-in user's token must carry the user_impersonation scope and an app-only token must hold the Render.Access application permission (see Who may call).
Client Credentials (service-to-service)
Used by source systems: Business Central, Dynamics 365 Sales, Dynamics GP, the Power Platform connector, and your own scripts. No user is involved. Each system authenticates as its own connector app, with that app's client ID and secret, and requests a token for:
api://<dispatcher-app-client-id>/.default<dispatcher-app-client-id> is the client ID of "REFRACT Dispatcher API". The scope is the same for every caller; only the client ID and secret differ.
The connector app must hold the Render.Access application permission on "REFRACT Dispatcher API", with admin consent, or every call is refused with 403 and code ROLE_MISSING. A connector that reads document records also needs Lifecycle.Reader. infra/deploy.ps1 creates both permissions but grants them to no app.
See Connect a source system for why each system gets its own connector, the portal steps, and each system's settings.
Delegated (a person signs in)
Used when a person is signed in: REFRACT Lifecycle in SharePoint, and API testing in Postman. The token carries the person's identity, the user_impersonation scope, and any roles assigned to the person.
REFRACT Lifecycle (SPFx). The refract-spfx.sppkg package asks for the REFRACT Dispatcher API / user_impersonation permission. Deploying the package to the App Catalog does not grant it. An administrator must approve the pending request in the SharePoint admin center -> Advanced -> API access; an Application Administrator can approve it. The approval adds the delegated permission to SharePoint's "SharePoint Online Client Extensibility Web Application Principal", which is the client REFRACT Lifecycle signs in through. Until the request is approved, every REFRACT Lifecycle call to the Dispatcher fails. You approve it once per tenant, not once per site.
Postman and your own tools. Register a testing app and give it the delegated permission user_impersonation on "REFRACT Dispatcher API", then grant admin consent: the scope is defined as needing an administrator's consent. Request api://<dispatcher-app-client-id>/.default. See Testing with Postman.
Earlier instructions signed in as the Dispatcher API itself
Earlier versions of this page had Postman sign in as "REFRACT Dispatcher API" itself, with the bare scope <dispatcher-app-client-id>/.default. Microsoft Entra ID refuses the api:// form when an app requests a token for itself (AADSTS90009), which is why that setup used a different scope. Use a separate testing app instead, so that every caller uses the same api:// scope and "REFRACT Dispatcher API" never acts as a client.
To read document records, the person also needs the Lifecycle.Reader role. See Give people access to document records.
JWT Validation
Regardless of which flow produced the token, the Dispatcher validates the same claims on every request:
| Claim | Validates | Configured via |
|---|---|---|
aud | Token was issued for "REFRACT Dispatcher API". The app's client ID is accepted with or without the api:// prefix. | JWT_AUDIENCE app setting, which infra/deploy.ps1 sets to that client ID |
iss | Token was issued by this tenant's own Microsoft Entra ID | JWT_ISSUER app setting |
tid | Token belongs to the authorised tenant | AZURE_TENANT_ID app setting |
exp | Token has not expired | - |
Claim validation is performed by requireTenantScope, which wraps the underlying JWT check and additionally enforces that the token's tid matches the Dispatcher's own AZURE_TENANT_ID.
Who may call
After those checks, the Dispatcher decides whether this kind of caller may call it at all. A token with a non-empty scp claim is a signed-in user's token; any other token is app-only.
-
A signed-in user's token must carry the
user_impersonationscope. REFRACT Lifecycle gets it when the SPFx API access request is approved. Any other client app, such as a Postman testing app, must be granted the delegated permission with admin consent. Without it:{ "error": "Forbidden", "code": "SCOPE_MISSING", "scope": "user_impersonation", "message": "Your sign-in token does not carry the user_impersonation permission of the "REFRACT Dispatcher API" app, so the request was refused. A Microsoft Entra administrator grants it to the application you signed in with: Microsoft Entra admin center > App registrations > (that application) > API permissions > Add a permission > REFRACT Dispatcher API > Delegated permissions > user_impersonation, then Grant admin consent. Then sign out and sign in again." } -
An app-only token must hold
Render.Accessin itsrolesclaim. Without it:{ "error": "Forbidden", "code": "ROLE_MISSING", "role": "Render.Access", "message": "This application may not call the "REFRACT Dispatcher API" app. It needs the Render.Access application permission. A Microsoft Entra administrator grants it: Microsoft Entra admin center > App registrations > (this application) > API permissions > Add a permission > REFRACT Dispatcher API > Application permissions > Render.Access, then Grant admin consent." }
Both rules apply to every authenticated route, with HTTP 403. Only /api/healthz, /api/audience-config, /api/audit-config, GET /api/render?ping=true, the routes portal links use (which carry their own tokens), and the eSign portal's signed callbacks are exempt.
Decisions are made by people. An app-only token cannot approve, reject, request changes on, or escalate a workflow, make a governance decision, or decide a batch, whatever roles it holds: 403 with code APP_CANNOT_DECIDE and the message "An application cannot make this decision. Approvals, rejections, requests for changes, governance decisions and escalations are made by a signed-in person." An app-only token is also never a workflow participant, even of a workflow it created.
The Lifecycle.Reader role
Routes that read document records (audit events, signing and delivery status, workflow data and exports, opening a workflow for review, stored files opened through /api/doc and /api/gateway/v1/documents/open, evidence exports and archives, Section 508 outputs, the integrity verdict, verification and reproduction, explain traces and PDFs, and batch records), a signed-in user's re-render of a stored payload, and a signed-in user's send of a stored document (POST /api/esign/session, POST /api/esign/capture, POST /api/delivery), also require Lifecycle.Reader in the token's roles claim, and return 403 with code ROLE_MISSING without it. Both flows can carry it:
- Delegated: assign the role to the user, or to a group they belong to, under Enterprise applications -> REFRACT Dispatcher API -> Users and groups. It arrives in tokens issued after the assignment, so the user should sign out and sign in again. See Give people access to document records.
- Client credentials: grant the role to the calling app as an application permission (API permissions -> Add a permission -> APIs my organization uses -> REFRACT Dispatcher API -> Application permissions -> Lifecycle.Reader), then grant admin consent. An app-only token needs
Render.Accessas well;Lifecycle.Readeralone is refused. TheROLE_MISSINGmessage forLifecycle.Readeris written for a person; for an app, the fix is these API permissions steps. An app sends a stored document withRender.Accessalone.
See Access: the Lifecycle.Reader Role for the full list of what it covers.
JWT_REQUIRED fails closed
JWT_REQUIRED defaults to enforcing JWT validation: the only value that turns validation off is the literal string "false". Any other value, including an unset or misconfigured setting, keeps JWT enforcement on.
Next Steps
- Connect a source system - Connector apps, admin consent, and each system's settings
- Testing with Postman - Postman configuration, as an app or as a person
- Power Platform Connector Setup - Client-credentials setup for the connector
- REFRACT Dispatcher API Overview - Endpoint list and the two auth models compared
REFRACT Dispatcher API
Overview of the customer-hosted REFRACT Dispatcher's HTTP API, its Microsoft Entra ID App Registration, and the two authentication models available to callers.
Connect a source system
Which Microsoft Entra ID app registrations a REFRACT deployment creates, which ones you create, and how to connect Business Central, Dynamics 365 Sales, Dynamics GP, Power Platform, or your own scripts to the Dispatcher with a connector app per system.