Hi,
We are implementing external dashboard embedding in Azure Databricks and want to avoid using client secrets by leveraging **Azure Managed Identity** with **OAuth token federation** for generating the embedded report token.
Following OAuth token federation documentation, we successfully obtain an AAD token using:
credential = ManagedIdentityCredential(client_id=CONFIG['service_principal_id'])
aad_token_res = credential.get_token("api://AzureADTokenExchange/.default")
aad_token = aad_token_res.token
Then, we exchange this token for a Databricks **all-apis** token using:
federated_params = {
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"client_id": CONFIG["service_principal_id"],
"subject_token": aad_token,
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"scope": "all-apis"
}
Next, we call `/published/tokeninfo` with `external_viewer_id` and `external_value` to retrieve `authorization_details` and `custom_claim`. This step works as expected and returns the same data as when using Basic Auth with a service principal secret.
However, when we perform the **scoped token exchange** using OAuth federation:
scoped_params = {
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"client_id": "<Databricks SP UUID>",
"custom_claim": "urn:aibi:external_data:testss:test:DASHBOARD_ID",
"subject_token": aad_token,
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"authorization_details": json.dumps(token_info["authorization_details"]),
}
The resulting JWT **does not include the `custom.claim`**. It only contains `authorization_details` and `scope`. In contrast, when using Basic Auth + SP secret, the scoped token includes:
"custom": {
"claim": "urn:aibi:external_data:<external_value>:<external_viewer_id>:<dashboard_id>"
}
Without this claim, embedding fails with:
{"message":"BAD_REQUEST","name":"Dashboard ID is missing in token claim."}
Question
Is this a known limitation of the current public preview for OAuth token federation? If so, is there an ETA for supporting **custom claim injection** in scoped tokens for external embedding?
Code Summary (Federation Flow):
scoped_params = {
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"client_id": "<Databricks SP UUID>",
"custom_claim": "urn:aibi:external_data:testss:test:DASHBOARD_ID",
"subject_token": aad_token, # MI token for api://AzureADTokenExchange/.default
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"authorization_details": json.dumps(token_info["authorization_details"]),
}
response = [requests.post](
f"{instance_url}/oidc/v1/token",
headers={"Content-Type": "application/x-www-form-urlencoded"},
data=scoped_params
)
Decoded JWT (Federation):
{
"client_id": "…",
"scope": "…",
...
"authorization_details": […]
}
Decoded JWT (Basic Auth):
{
"custom": {
"claim": "urn:aibi:external_data:testss:test:<dashboard_id>"
},
"client_id": "…",
"scope": "…",
"authorization_details": […]
...
}
References:
- [Embedding dashboards for external users](https://learn.microsoft.com/en-us/azure/databricks/dashboards/embedding/external-embed)
- [OAuth token federation overview](https://learn.microsoft.com/en-us/azure/databricks/dev-tools/auth/oauth-federation)
- [Configure federation policy](https://learn.microsoft.com/en-us/azure/databricks/dev-tools/auth/oauth-federation-policy)