Join us for an expert-led overview of the tools and concepts you'll need to pass exam PL-300. The first session starts on June 11th. See you there!
Get registeredPower BI is turning 10! Let’s celebrate together with dataviz contests, interactive sessions, and giveaways. Register now.
Hi.
I have a similar problem to the following forum posted by @akarkal : Solved: Update DataSet Credentials using Service Principal - Microsoft Fabric Community
Similarly, I am trying to update datasource credentials of a dataset using a service principal through the C# PowerBI Client Library.
However, no fixes on my part have worked.
Here is the setup:
Here is the 2 main parts of my script after getting an authenticated Power BI Client:
Getting the Key (PAT):
var secretClient = new SecretClient(new Uri(keyVaultUri), new DefaultAzureCredential());
KeyVaultSecret secret = await secretClient.GetSecretAsync(secretName, secretVersion);
Trying to update datasource:
var datasources = (await pbiClient.Datasets.GetDatasourcesAsAdminAsync(datasetId)).Value;
var datasource = datasources.First();
var gatewayId = datasource.GatewayId ?? throw new InvalidOperationException("Datasource is not associated with a gateway.");
var datasourceId = datasource.DatasourceId ?? throw new InvalidOperationException("Datasource does not have a DatasourceId.");
var credentials = new KeyCredentials(key);
var credentialDetails = new CredentialDetails(
credentials,
PrivacyLevel.None,
EncryptedConnection.NotEncrypted
);
await pbiClient.Datasets.TakeOverAsync(workspaceId, datasetId);
await pbiClient.Gateways.UpdateDatasourceAsync(gatewayId, datasourceId, new UpdateDatasourceRequest(credentialDetails));
At the last line of code, I get the PowerBINotAuthorized error.
I also tried doing a basic authentication where the username is the SP's ClientId and the password is the SP's password. However, I got the following error:
Failed to update datasource: One or more errors occurred.
Inner Exception: {
"code": "BadRequest",
"message": "Bad Request",
"details": [
{
"message": "Invalid value",
"target": "datasourceDelta"
}
]
}
This error might be because Basic credentials might not work with Service Principals.
I haven't really found a solution even with the related forum. As such, any help would be appreciated.
Thanks.
You're getting the PowerBiNotAuthorized error likely because Azure Databricks credentials cannot be updated using a service principal with KeyCredentials — it doesn’t work that way for cloud datasources like Databricks.
Here’s what usually works, try this, use Basic credentials (not KeyCredentials), and pass the Databricks Personal Access Token (PAT) as the password.
Like this, In Csharp use - var credentials = new BasicCredentials("token", secret.Value); // "token" can be any string
And then same in csharp use - var credentialDetails = new CredentialDetails(credentials, PrivacyLevel.Private,EncryptedConnection.Encrypted).
And make sure that your service principal is allowed in Admin Portal → Tenant Settings → Developer settings. After calling TakeOverAsync, fetch the datasources again before updating
And remember this, Use BasicCredentials, not KeyCredentials.
Use PAT as password, and any dummy username like "token".
Confirm SP permissions and tenant settings.
Call TakeOverAsync, then get datasources again before updating
-----------------------------------------------------------------------------------------------------------------------------
If this response helps, consider marking it as “Accept as solution” and giving a “kudos” to assist other community members.
Regards,
Akhil.
Hi, thank you so much for the lead. However, after the service principal takes over the dataset, the datasource that I get has no datasourceId nor a gatewayId. Relevant code:
var datasource = (await pbiClient.Datasets.GetDatasourcesAsAdminAsync(datasetId)).Value.First();
await pbiClient.Datasets.TakeOverAsync(workspaceId, datasetId);
datasource = (await pbiClient.Datasets.GetDatasourcesAsAdminAsync(datasetId)).Value.First();
var gatewayId = datasource.GatewayId ?? throw new InvalidOperationException("Datasource is not associated with a gateway."); // errors with no gateway id
var datasourceId = datasource.DatasourceId ?? throw new InvalidOperationException("Datasource does not have a DatasourceId."); // errors with no datasource id
Console.WriteLine($"Gateway ID: {gatewayId}, Datasource ID: {datasourceId}");
await pbiClient.Gateways.UpdateDatasourceAsync(gatewayId, datasourceId, new UpdateDatasourceRequest(credentialDetails));
I fixed this issue by binding the dataset to the same gateway and datasource after taking over as the service principal. However, I now get a bad request error with all different credential types I tried with (Basic, Key, and OAuth2)
Hey @ParsaJafarian Glad to hear you made progress and figured out that the dataset needed to be bound again after the service principal took over, that's a tricky step that often gets missed.
Now, about the BadRequest error you're seeing when trying to update the credentials: I've run into the exact same issue before when working with Azure Databricks and a service principal, and here's what finally worked for me (after lots of trial and error!).
What finally solved it is, first off, don’t use KeyCredentials for Databricks. It just doesn't work. Instead, go with BasicCredentials, but here's the trick — for the username, just use something like "token", and for the password, use the actual Databricks Personal Access Token (PAT) you fetched from Key Vault.
So basically in csharp
var credentials = new BasicCredentials("token", patFromKeyVault);
var credentialDetails = new CredentialDetails(credentials, PrivacyLevel.Private, EncryptedConnection.Encrypted);
***Now here’s the important bit: after you do the TakeOverAsync, you must rebind the dataset to the gateway again before you try updating the credentials. Even if the gateway looks the same, it won’t “stick” unless you explicitly rebind.
In csharp try the below
await pbiClient.Datasets.BindToGatewayAsync(datasetId, new BindToGatewayRequest { GatewayObjectId = gatewayId });
After that, fetch the data sources again don’t reuse the earlier result because now the binding is fresh and should return a valid datasourceId and gatewayId.
Then update the credentials using those refreshed IDs.
Make sure the service principal is allowed in the Tenant Settings > Developer Settings, and that it has all the right API permissions (you’ve likely done this, but just worth double-checking).
---------------------------------------------------------------------------------------------------------
If this response helps, consider marking it as “Accept as solution” and giving a “kudos” to assist other community members.
Regards,
Akhil.
Hi @v-agajavelly . Thank you for your response again. Actually those are all what I did. However, I still get bad request. That might be because I am just using the wrong PAT or clientId so I'll check on my end. Here is my C# script:
using var pbiClient = await PowerBIAuth.GetPowerBIClientAsync();
var key = await PowerBIAuth.GetPAT();
var credentials = new BasicCredentials("token", key);
var credentialDetails = new CredentialDetails(
credentials,
PrivacyLevel.Private,
EncryptedConnection.Encrypted
);
//=================MAIN LOGIC===================
var datasources = (await pbiClient.Datasets.GetDatasourcesAsAdminAsync(datasetId)).Value;
var datasource = datasources.First();
var gatewayId = datasource.GatewayId ?? throw new InvalidOperationException("Datasource is not associated with a gateway.");
var datasourceId = datasource.DatasourceId ?? throw new InvalidOperationException("Datasource does not have a DatasourceId.");
await pbiClient.Datasets.TakeOverAsync(groupId, datasetId);
await pbiClient.Datasets.BindToGatewayInGroupAsync(groupId, datasetId, new BindToGatewayRequest(gatewayId, [datasourceId]));
//Get the datasource again after binding to ensure it has the correct gateway and datasource ID
datasources = (await pbiClient.Datasets.GetDatasourcesAsAdminAsync(datasetId)).Value;
datasource = datasources.First();
gatewayId = datasource.GatewayId ?? throw new InvalidOperationException("Datasource is not associated with a gateway.");
datasourceId = datasource.DatasourceId ?? throw new InvalidOperationException("Datasource does not have a DatasourceId.");
await pbiClient.Gateways.UpdateDatasourceAsync(gatewayId, datasourceId, new UpdateDatasourceRequest(credentialDetails));
Thanks for sharing your code and walking through the full flow—I really appreciate that level of detail! From what I see, everything looks wired up correctly.
That said, since you're still getting a BadRequest at the UpdateDatasourceAsync step, step, I think we might be dealing with one of two things.
First try The Personal Access Token (PAT) might not be what Power BI is expecting.
Just to double-check, is the key you're retrieving here via await PowerBIAuth.GetPAT() definitely a Databricks Personal Access Token? It should be.
The reason I’m asking is, if you're using the service principal's clientId or clientSecret here instead of a Databricks PAT, Power BI will quietly reject the credentials (even though the structure looks right) and throw a vague BadRequest error.
Also, tiny thing: you can test if the PAT is working using a tool like Azure Data Studio or DBeaver — just plug in:
Once Check what kind of datasource Power BI thinks you're dealing with.
After binding, try logging the details of the datasource like this in csharp.
Console.WriteLine(JsonConvert.SerializeObject(datasource, Formatting.Indented));
You're looking for something like json?
"datasourceType": "Extension",
"connectionDetails": {
"server": "<your-databricks-url>",
"database": "<your-db-name>"
}
Sometimes the dataset might be pointing to a slightly different type of source (depending on how it was originally created), and that could block credential updates.
Please try updating credentials manually in Power BI Service, Just to isolate the issue, go to Power BI web portal -- dataset settings -- edit credentials -- and try using:
---------------------------------------------------------------------------------------------------------
If this response helps, consider marking it as “Accept as solution” and giving a “kudos” to assist other community members.
Regards,
Akhil.
For your reference, this is the code for `GetPAT()`
public static async Task<string> GetPAT()
{
const string secretName = "";
var secretClient = new SecretClient(new Uri(keyVaultUri), new DefaultAzureCredential());
KeyVaultSecret secret = await secretClient.GetSecretAsync(secretName);
return secret.Value;
}
You can’t log into the Power BI Service (web portal) as a service principal in the usual interactive way (like you would with a regular user account). Service principals are meant to be used programmatically meaning only via APIs or SDKs and don’t have a UI login experience.
So when I suggested trying to update the credentials manually please try in the Power BI Service, that would need to be done using a regular user account that has access to the same dataset and workspace.
Here’s what I’d suggest.
If that works, then awesome — it confirms the token is valid and the dataset can accept it.
If it fails, then at least the UI might show you a clearer error like “invalid credentials” or “cannot connect,” which can be much easier to debug than a generic BadRequest from the API.
If Your GetPAT() method looks perfect — it’s just important to make sure that:
---------------------------------------------------------------------------------------------------------
If this response helps, consider marking it as “Accept as solution” and giving a “kudos” to assist other community members.
Regards,
Akhil.
Hi @v-agajavelly ,
I am getting an error when I manually use the PAT so I think I will check if the PAT is right.
Just wanted to check in did you get a chance to verify if the PAT you're using is valid? Sometimes it’s something small like a missing permission or an expired token that trips things up.
If it’s still giving you trouble, feel free to share what error you’re seeing, happy to help you troubleshoot it.
Regards,
Akhil
Thank you @v-agajavelly. Would you know how to manually change as a service principal? I am not sure how to log in to Power BI Service as a Service Principal.
User | Count |
---|---|
13 | |
7 | |
2 | |
2 | |
2 |
User | Count |
---|---|
3 | |
3 | |
3 | |
2 | |
2 |