a week ago - last edited a week ago
Calling get_token() on a Unity Catalog service credential fails for any scope using the api:// App ID URI format. Only https://-scheme resource scopes succeed. The same api:// scopes work correctly with a service principal.
credential = dbutils.credentials.getServiceCredentialsProvider(
"managed-identity"
)
scopes = [
"https://vault.azure.net/.default",
"api://<domain>/.default",
"api://<domain>",
"api://<domain>/",
]
for scope in scopes:
try:
result = credential.get_token(scope)
print(scope, "OK; expires:", result.expires_on)
except Exception as error:
print(scope, type(error).__name__, str(error))The first scope succeeds. Every api:// variant fails with:
Error while retrieving temporary credentials: '<scope>' is not a valid URI
Substituting the app registration's Application (client) ID GUID — both as api://<client-id>/.default and as a bare <client-id>/.default — fails identically.
This isolates the failure to scope-string validation in the temporary-credentials path, not to the credential, the managed identity, or its permissions — the same credential object returns a valid token for the https:// scope in the same loop.
On the same compute, in the same notebook, the identical api:// scope returns a valid token when requested through a service principal with azure.identity instead of the service credential provider:
from azure.identity import ClientSecretCredential
client_id = dbutils.secrets.get(scope="keyvault", key="client_id")
client_secret = dbutils.secrets.get(scope="keyvault", key="client_secret")
tenant_id = dbutils.secrets.get(scope="keyvault", key="tenant_id")
credential = ClientSecretCredential(
tenant_id=tenant_id,
client_id=client_id,
client_secret=client_secret
)
scopes = ["api://<domain>/.default"]
for scope in scopes:
try:
result = credential.get_token(scope)
print(scope, "OK; expires:", result.expires_on)
except Exception as error:
print(scope, type(error).__name__, str(error))api://<domain>/.default returns a token successfully.
This confirms the scope string is valid and that the app registration is correctly configured. The rejection originates solely in the Databricks temporary-credentials layer.
Identical behavior on both.
Our security policy mandates managed identities. Unity Catalog service credentials are therefore our only supported path for machine-to-machine authentication from Databricks to internal APIs. This validation blocks that path entirely for any internal API using the default api:// identifier URI.
The ClientSecretCredential approach shown above works, but is not a viable workaround for us: it requires storing and rotating a client secret, which is precisely what the managed-identity mandate exists to avoid.
9 hours ago
Hello, a quick update on this
I reached out to the databricks support team and they confirm that Unity Catalog service credentials do not support "api://" URIs. this is a known product limitation. They asked me to file for a feature request with Databricks.
a week ago
Hi @Oumeima ,
Thank you for the detailed reproduction. As per my understanding of the issue you are facing, your isolation of the problem is entirely correct.
This behavior is caused by an undocumented strict URI validation bug within the Databricks dbutils.credentials layer. When you request a token, the scope parameter (typically ending in /.default) tells Entra ID exactly which target API you want to access and automatically requests all permissions previously granted to your managed identity for that specific resource.
However, before passing this scope string to Azure to generate the token, the Databricks temporary-credentials path validates it. It currently expects standard Azure resource endpoints starting with https:// and inadvertently rejects api:// schemes as invalid URIs. Because this is an internal validation oversight rather than an intentional platform constraint, it is not mentioned in the official Databricks documentation.
To maintain strict compliance with your managed identity mandate without using client secrets, the most reliable workaround is to modify the Application ID URI of your internal API in the Azure Portal. Entra ID fully supports HTTPS-based Application ID URIs. By changing your exposed API's identifier from the default api://<client-id
a week ago
hello @ShamenParis,
sadly we cannot add another app ID URI for internal reasons. I filed for a support ticket and we'll see if they remove this restriction 🙂
a week ago
Hi @Oumeima ,
Totally understand. Let's hope support comes through with a fix🤞
9 hours ago
Hello, a quick update on this
I reached out to the databricks support team and they confirm that Unity Catalog service credentials do not support "api://" URIs. this is a known product limitation. They asked me to file for a feature request with Databricks.