The three registrations
The external Entra client ID differs from the BOW Entra client ID. The field External Entra application (client) ID contains the external application’s ID.
Prerequisites
- A tenant-specific Microsoft Entra SSO provider configured in BOW. This flow supports the Microsoft public cloud and tenant GUID authorities.
- Your external app has delegated consent for
api://BOW_ENTRA_CLIENT_ID/access_as_user. - The BOW Entra registration has the delegated permissions and consent required by the Power BI connector or Fabric connector.
- Each user has the required permissions on the underlying Microsoft data.
- New users have a valid invitation to the OAuth app’s BOW organization, or that organization has enabled domain signup for their Entra login domain. Domain signup requires the corresponding BOW license feature.
- Your application has a backend that can protect both its Entra secret and its BOW custom-app secret.
Configure BOW’s Entra provider
Merge this provider into your existingbow-config.yaml; keep your database, encryption, license, and other settings.
https://YOUR_BOW_HOST/api/auth/entra/callback on the BOW Entra registration. The external application’s Microsoft callback belongs on the external Entra registration and points to your application, for example http://localhost:3000/entra/callback in development.
These are separate from the callback URIs used by BOW’s Authorization Code + PKCE flow.
Register the custom app in BOW
- Open Settings → Channels → OAuth Apps and select Register app, or edit an existing app.
- Select BOW app for reports and completions.
- Enable Enable Entra token exchange.
- Select the configured Entra SSO provider.
- Enter the External Entra application (client) ID.
- Copy the displayed tenant ID and required scope into your external application’s configuration.
- Save and store the BOW client ID and one-time secret on your backend.
Configure admission and the data connection
For a new user, BOW checks the target organization’s existing rules:- A current invitation is accepted and its assigned roles and groups are applied.
- Otherwise, an enabled domain signup policy must admit the user’s Entra login domain. The configured signup role and seat limits apply.
- If neither applies, the exchange fails without creating a user.
Request and exchange the token
Have your external application’s Microsoft authentication library acquire a delegated access token for:azp for v2 tokens or appid for v1 tokens).
From your backend:
token_type: Bearer, issued_token_type, expires_in, and scope. It has no BOW refresh token. Its lifetime is at most one hour and never longer than the submitted Entra token’s remaining lifetime.
Send it as Authorization: Bearer ... when calling the report and streaming completion APIs. The organization is pinned to the custom app; an organization header cannot switch it.
When renewal is needed, your backend acquires a fresh Entra access token through its Microsoft authentication library and exchanges it again. BOW does not store the incoming Entra assertion.
Verify the complete flow
Use a test account that has never registered with BOW:- Invite the account or enable domain signup for its domain.
- Sign in only through the external application.
- Exchange the access token and call
GET /api/users/whoamiwith the returned BOW token. - Check that one BOW user and one membership were created with the intended role.
- Run a small read-only Power BI query through the intended agent.
- Repeat the exchange and verify that it reuses the same user.
- Verify that a non-invited account from a disallowed domain is rejected.
tools/agent/entra_exchange_demo.py. It uses a loopback callback, PKCE and state, and keeps tokens on the local server.
Troubleshooting
Changing or disabling the Entra exchange configuration invalidates tokens issued through that configuration. Existing Authorization Code + PKCE tokens are unaffected by an exchange-only settings change. Changing access surfaces retains the existing behavior of revoking that app’s grants and tokens.
Appendix: expose and grant access_as_user
On the BOW Entra application:- Open App registrations → your BOW application → Expose an API.
- Set the Application ID URI to
api://BOW_ENTRA_CLIENT_ID. - Add an enabled scope named
access_as_user, with a clear description such as “Access BOW as the signed-in user.” Choose the consent policy appropriate for your tenant.
- Open API permissions → Add a permission → My APIs.
- Select the BOW API, choose Delegated permissions, and select
access_as_user. - Add the permission and arrange the required administrator consent.
