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

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
DanielRamos
Frequent Visitor

Embedding Dashboard on Salesforce throws error when using RLS

Please, help.

I'm using SalesforceAppOwnsDataEmbedding to display a Dashboard in Salesforce, everything works well, inclusively I'm able to send Report Level Filters.

However, if Row Level Security is used in Dashboard, then error occurs.

 

(Displayed error) Generate Token Error: OK
(Internal Error) Bad Request, Error 400

 

I already tried using identities for api body with no success.

 

Not sure if App Registration in Azure requires specific permission over the PowerBi Service Api. (read/write)

 

Thanks in advance!

 

Class method where error occurs:

 

// Call to Power BI Service API to get embed token for report        
        HttpRequest reqGetEmbedToken = new HttpRequest();
        reqGetEmbedToken.setMethod('POST');
        String urlGetEmbedToken = 'https://api.powerbi.com/v1.0/myorg/groups/' + WorkspaceId + '/reports/' + ReportId + '/GenerateToken';
        reqGetEmbedToken.setEndpoint(urlGetEmbedToken);
        System.debug('new method with devEnv as Identity');
        reqGetEmbedToken.setHeader('Authorization', 'Bearer ' + access_token);    
        reqGetEmbedToken.setBody(
            '{'
            +'"datasets": [{"id": "'+powerBiReport.datasetId+'"}]'
            +',"reports": [{"id": "'+powerBiReport.id+'"}]'
            +',"identities":['
                +'{"username":"appRegistrationObjectId","roles":["Security"],"datasets":["'+powerBiReport.datasetId+'"]}'
                +'{"username":"appRegistrationClientId","roles":["Security"],"datasets":["'+powerBiReport.datasetId+'"]}'
            +']'
            +'}');
        System.debug('complete reqGetembedToken varialbe debugging '+reqGetEmbedToken.getBody());
    
        HttpResponse responseEmbedToken = http.send(reqGetEmbedToken);

 

 

1 ACCEPTED SOLUTION
DanielRamos
Frequent Visitor

Finally achieved this embedding!!! 🎉

Sharing solution in case someone's struggling with something similar.

 

My scenario was; I'm using a POST call to endpoint API GenerateTokenInGroup, my Dahsboard uses RLS, so it is required to include "identities" in the "Request Body" json, seems like I was not including all the required data on each section of the HttpRequest.

 

Important!

  • Now I included Content-Type: application/json to the header of request
  • Request Body is now composed with accessLevel: View, and identities using Service Principal Id (Application Client Id) as the username.
  • I created a new Role with no filters and assigned to Service Principal
    • (This allows me to apply ReportLevelFilters for dynamically filtering from Salesforce)
  • Provided the required API permissions on App Registration (Service Principal) on Azure.
    • Delegated Permissions, Power Bi Service; Report.ReadWrite.All, Dataset.ReadWrite.All, Content.Create

Full HttpRequest code

// Call to Power BI Service API to get embed token for report        
        HttpRequest reqGetEmbedToken = new HttpRequest();
        reqGetEmbedToken.setMethod('POST');
        String urlGetEmbedToken = 'https://api.powerbi.com/v1.0/myorg/groups/' + WorkspaceId + '/reports/' + ReportId + '/GenerateToken';
        reqGetEmbedToken.setEndpoint(urlGetEmbedToken);
        System.debug('setEndpoint = '+urlGetEmbedToken);
        reqGetEmbedToken.setHeader('Authorization', 'Bearer ' + access_token);
        reqGetEmbedToken.setHeader('Content-Type', 'application/json');
        system.debug('setHeader = '+reqGetembedToken.getHeader('Authorization'));
        reqGetEmbedToken.setBody(
            '{'
                +'"accessLevel":"View"'
                +',"identities":['
                    +'{"username":"1eac8b84-11a3-4f67-b308-c9ab0a7b8da0","roles":["noRlsFilters"],"datasets":["'+powerBiReport.datasetId+'"]}'
                +']'
            +'}');
        System.debug('setBody = '+reqGetEmbedToken.getBody());
    
        HttpResponse responseEmbedToken;
        try {                        
            responseEmbedToken = http.send(reqGetEmbedToken);
            System.debug('http send successfully');
            system.debug(responseEmbedToken);
        } catch (Exception error) {
            system.debug('Error Catched');
            System.debug(error);
        }

 

Response code is now 200 and Token is successfully generated,

Dashboard is displaying and filtering is correctly applying.

 

Hooray!

View solution in original post

5 REPLIES 5
DanielRamos
Frequent Visitor

Finally achieved this embedding!!! 🎉

Sharing solution in case someone's struggling with something similar.

 

My scenario was; I'm using a POST call to endpoint API GenerateTokenInGroup, my Dahsboard uses RLS, so it is required to include "identities" in the "Request Body" json, seems like I was not including all the required data on each section of the HttpRequest.

 

Important!

  • Now I included Content-Type: application/json to the header of request
  • Request Body is now composed with accessLevel: View, and identities using Service Principal Id (Application Client Id) as the username.
  • I created a new Role with no filters and assigned to Service Principal
    • (This allows me to apply ReportLevelFilters for dynamically filtering from Salesforce)
  • Provided the required API permissions on App Registration (Service Principal) on Azure.
    • Delegated Permissions, Power Bi Service; Report.ReadWrite.All, Dataset.ReadWrite.All, Content.Create

Full HttpRequest code

// Call to Power BI Service API to get embed token for report        
        HttpRequest reqGetEmbedToken = new HttpRequest();
        reqGetEmbedToken.setMethod('POST');
        String urlGetEmbedToken = 'https://api.powerbi.com/v1.0/myorg/groups/' + WorkspaceId + '/reports/' + ReportId + '/GenerateToken';
        reqGetEmbedToken.setEndpoint(urlGetEmbedToken);
        System.debug('setEndpoint = '+urlGetEmbedToken);
        reqGetEmbedToken.setHeader('Authorization', 'Bearer ' + access_token);
        reqGetEmbedToken.setHeader('Content-Type', 'application/json');
        system.debug('setHeader = '+reqGetembedToken.getHeader('Authorization'));
        reqGetEmbedToken.setBody(
            '{'
                +'"accessLevel":"View"'
                +',"identities":['
                    +'{"username":"1eac8b84-11a3-4f67-b308-c9ab0a7b8da0","roles":["noRlsFilters"],"datasets":["'+powerBiReport.datasetId+'"]}'
                +']'
            +'}');
        System.debug('setBody = '+reqGetEmbedToken.getBody());
    
        HttpResponse responseEmbedToken;
        try {                        
            responseEmbedToken = http.send(reqGetEmbedToken);
            System.debug('http send successfully');
            system.debug(responseEmbedToken);
        } catch (Exception error) {
            system.debug('Error Catched');
            System.debug(error);
        }

 

Response code is now 200 and Token is successfully generated,

Dashboard is displaying and filtering is correctly applying.

 

Hooray!

Hi @DanielRamos ,

It's glad to hear that your problem has been resolved. And thanks for sharing your solution here. Much appreciated!

Best Regards 

Community Support Team _ Rena
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.
v-yiruan-msft
Community Support
Community Support

Hi @DanielRamos ,

Please check if you hit any following limitation, you can find the details in this official documentation.

  • The user that generates the embed token has to be a member or admin in both workspaces (the dataset workspace and the report workspace).
  • When generating the embed token, you need to provide a username and a role. If you don't, one of the following will occur, depending on if the token is being generated by service principal or master user:
    • For a service principal, token generation will fail.
    • For a master user, token generation will succeed but the data will not be filtered (all the data is returned).

Best Regards

Community Support Team _ Rena
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Hi @v-yiruan-msft 

 

Thank you for your quick response.

Those settings were configured from beggining: my Service Principal is admin of Workspace, I'm sending the username and roles within the body of my http call to end point.

Interesting thing here is that when I remove any RLS from Dashboard in PowerBi Desktop and Publish, embedding successfully works.

 

Providing more detail, the app I'm deploying seems like uses the GenerateTokenInGroup Api

Is there any compatibility issue with RLS?

 

Thanks in advance

Hi @DanielRamos ,

Please check the following limitation when apply RLS,  you can find the details in this official documentation.

  • Service principals cannot be added to an RLS role. Accordingly, RLS won’t be applied for apps using a service principal as the final effective identity.

Best Regards

Community Support Team _ Rena
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

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