Could someone clarify why the POST /api/v2/oauth/token endpoint returns a 403 Forbidden with error code SCOPE_MISMATCH when requesting purview:all for a multi-tenant setup? We are using SDK v1.42.0 and the service principal has admin consent. The integration works in the staging org but fails in production during the initial handshake. The request payload includes the correct client_id and redirect_uri. Is there a hidden rate limit or additional permission required for cross-org token issuance?
You need to verify the service principal’s granted permissions in the Azure AD admin center, as purview:all often requires explicit admin consent beyond the initial registration.
- Check Enterprise App > Permissions
- Verify “Grant admin consent” status
- Review Application Proxy mappings
The 403 SCOPE_MISMATCH error usually points to a mismatch between the registered application permissions and the actual token request payload, rather than just Azure AD consent. In high-concurrency load tests, this often happens when the token cache is stale or the client credentials are rotated without updating the integration config.
Try validating the token endpoint response directly with curl before relying on the SDK. This isolates the network layer from the application logic.
curl -X POST "https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id={client_id}" \
-d "client_secret={client_secret}" \
-d "scope=purview:all" \
-d "grant_type=client_credentials"
If this returns a valid token, the issue is likely in how the SDK handles the scope assertion during the handshake. The SDK might be appending additional scopes that are not pre-approved.
- Check the SDK initialization code to ensure it is not automatically adding
offline_accessor other scopes that were not explicitly granted in the Enterprise App permissions. - Verify that the
redirect_uriin the token request exactly matches the one registered in the Azure AD app manifest. Even a trailing slash difference causes a 403. - Review the AppFoundry integration logs for any scope negotiation failures. The production org might have stricter tenant-wide policies than staging.
- Consider implementing a token refresh mechanism in your load test script. If the token expires during a spike, the retry logic might be sending malformed requests.
This approach helps pinpoint whether the issue is with the permission grant or the request construction. The documentation suggests that explicit scope validation is required for cross-org integrations, especially in multi-tenant setups.