I tried the approach shown and was unable to make this work. I'm in an azure function, so the test function is invoked through an API call, but the rest is the same. The log data.
[2025-03-20T20:24:45.472Z] Acquiring access token with ClientSecretCredential...
[2025-03-20T20:24:46.077Z] Access token acquired successfully.
[2025-03-20T20:24:46.168Z] Opening connection to XMLA endpoint...
[2025-03-20T20:24:46.371Z] Error: When interactive authentication is not supported, an external access-token is required; either provide it in the connection-string or by setting the AccessToken property.
The call to connection.SessionID = accessToken; throws the error. I've tried for a day to find a way around this, but all the documentation and CoPilot keep running me in circles. Any idea how to fix this? I haven't found a combination of access methods with my service principal that allows me to establish a connection to the endpoint. I can connect via SSMS. Here is my entire function:
class TestXMLA
{
private readonly ILogger<TestXMLA> _logger;
public TestXMLA(ILogger<TestXMLA> logger)
{
_logger = logger;
}
// Inside the TestXMLA class
[Function("TestXMLA")]
public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
// Extract service principal details from the request body
string tenantId = data?.tenantId;
string workspaceId = data?.workspaceId;
string datasetName = data?.datasetName;
string clientId = data?.clientId;
string clientSecret = data?.clientSecret;
string scope = "https://analysis.windows.net/powerbi/api/.default";
string XMLAEndpoint = $"powerbi://api.powerbi.com/v1.0/myorg/{workspaceId}";
if (string.IsNullOrEmpty(tenantId) || string.IsNullOrEmpty(workspaceId) || string.IsNullOrEmpty(datasetName))
{
var response = req.CreateResponse(HttpStatusCode.BadRequest);
await response.WriteStringAsync("Missing tenant ID, workspace ID, or dataset name.");
return response;
}
try
{
// Step 1: Acquire access token using ClientSecretCredential (Service Principal)
_logger.LogInformation("Acquiring access token with ClientSecretCredential...");
var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var tokenRequestContext = new TokenRequestContext(new[] { scope });
var accessToken = (await credential.GetTokenAsync(tokenRequestContext)).Token;
_logger.LogInformation("Access token acquired successfully.");
// Step 2: Create connection string (without token in connection string)
string connectionString = $"Data Source={XMLAEndpoint};";
// Step 3: Open ADOMD connection
using (AdomdConnection connection = new AdomdConnection(connectionString))
{
// Apply the access token manually using SessionID
connection.SessionID = accessToken;
Console.WriteLine("Opening connection to XMLA endpoint...");
connection.Open();
// Step 4: Execute DAX Query
string query = "EVALUATE TOPN(500, Invoices)";
using (AdomdCommand command = new AdomdCommand(query, connection))
{
_logger.LogInformation("Executing query...");
using (AdomdDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
_logger.LogInformation(reader[0].ToString()); // Print first column (adjust as needed)
}
}
}
connection.Close();
_logger.LogInformation ("Connection closed successfully.");
var response = req.CreateResponse(HttpStatusCode.OK);
return response;
}
}
catch (Exception ex)
{
_logger.LogError($"Error: {ex.Message}");
var response = req.CreateResponse(HttpStatusCode.InternalServerError);
await response.WriteStringAsync($"Error: {ex.Message}");
return response;
}
}
}