Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Power BI is turning 10! Let’s celebrate together with dataviz contests, interactive sessions, and giveaways. Register now.

Reply
ParsaJafarian
Helper I
Helper I

Service Principal Credential Configuration Error: PowerBiNotAuthorized

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:

  • tenant settings has the toggle enabled for security group in which the service principal is a member of
  • Service Principal is an admin of the workspace
  • Service Principal takes over the dataset inside the C# script
  • Service Principal has Dataset.ReadWrite.All and Gateway.ReadWrite.All
  • The datasource that I want to change is a cloud datasource (Azure Databricks). As such, it is using a cloud gateway. 
  • I am trying to update the credentials through KEY credentials. 

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. 

11 REPLIES 11
v-agajavelly
Community Support
Community Support

Hi @ParsaJafarian 

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.

  • So the full flow that worked for me was.
  • Take over the dataset with the service principal
  • Rebind the dataset to the cloud gateway
  • Re-fetch the datasource info
  • Use BasicCredentials with "token" and the actual PAT
  • Update the datasource

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));

Hi @ParsaJafarian 

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.

  • Created from your Databricks workspace (under your profile settings → Access tokens)
  • Active and not expired
  • Belonging to a user that has access to the cluster or SQL endpoint you're connecting to

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:

  • Username: "token"
  • Password: your actual PAT
    That’s a quick way to confirm the token itself is good before going through the script again.

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:

  • Username: token
  • Password: your Databricks PAT

---------------------------------------------------------------------------------------------------------
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;
}

Hi @ParsaJafarian 

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.

  1. Log in to Power BI Service using a user account that:
    • Has Admin or Member access to the workspace the dataset lives in
    • Ideally is the same account that originally created the dataset (or has taken it over)
  2. Go to the dataset settings → Data source credentials
  3. Try entering the credentials manually.
    • Username: "token"
    • Password: (the same Databricks PAT you're pulling from Key Vault)

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:

  • The secretName points to the Databricks PAT in Key Vault (and not the SP client secret by mistake)
  • The Key Vault secret is actually the token string (no quotes or extra formatting).

---------------------------------------------------------------------------------------------------------
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. 

Hi @ParsaJafarian 

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. 

Helpful resources

Announcements
June 2025 Power BI Update Carousel

Power BI Monthly Update - June 2025

Check out the June 2025 Power BI update to learn about new features.

June 2025 community update carousel

Fabric Community Update - June 2025

Find out what's new and trending in the Fabric community.