cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
Highlighted
BaakWu Regular Visitor
Regular Visitor

Implementing RLS on Embedded where report token is received by Azure AD REST call.

Hello Everyone, 

 

I am attempting to implement RLS in our .Net Core application of embedding power BI. here is our current TokenDataCall

 

        /// <summary>
        /// Gets Token Credentials and access token for use with authenticating PowerBi api calls
        /// </summary>
        /// <returns></returns>
        public async Task<(TokenCredentials tokenCredentials, string accessToken)> GetTokenDataAsync()
        {
            try
            {
                var authorityUrl = $"{_azureSettings.Instance}{_azureSettings.TenantId}/oauth2/token";

                var oauthEndpoint = new Uri(authorityUrl);

                using (var client = new HttpClient())
                {
                    var result = await client.PostAsync(oauthEndpoint, new FormUrlEncodedContent(new[]
                    {
                        new KeyValuePair<string, string>("resource", _powerBiSettings.ResourceAddress),
                        new KeyValuePair<string, string>("client_id", _azureSettings.ClientId),
                        new KeyValuePair<string, string>("grant_type", "password"),
                        new KeyValuePair<string, string>("username", _powerBiSettings.MasterUser),
                        new KeyValuePair<string, string>("password", _powerBiSettings.MasterKey),
                        new KeyValuePair<string, string>("scope", "openid"),
                    }));

                    var content = await result.Content.ReadAsStringAsync();

                    var authenticationResult = JsonConvert.DeserializeObject<OAuthResult>(content);
                    return (new TokenCredentials(authenticationResult.AccessToken, _azureSettings.TokenType), authenticationResult.AccessToken);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                throw;
            }
        }

        private class OAuthResult
        {
            [JsonProperty("token_type")]
            public string TokenType { get; set; }
            [JsonProperty("scope")]
            public string Scope { get; set; }
            [JsonProperty("expires_in")]
            public int ExpiresIn { get; set; }
            [JsonProperty("ext_expires_in")]
            public int ExtExpiresIn { get; set; }
            [JsonProperty("expires_on")]
            public int ExpiresOn { get; set; }
            [JsonProperty("not_before")] 
            public int NotBefore { get; set; }
            [JsonProperty("resource")]
            public Uri Resource { get; set; }
            [JsonProperty("access_token")]
            public string AccessToken { get; set; }
            [JsonProperty("refresh_token")]
            public string RefreshToken { get; set; }
        }

I haven't found any documentation on how to use this token call to pass in the "Role" and "username" parameters found here.

https://docs.microsoft.com/en-us/power-bi/developer/embedded-row-level-security

 

Is there anyway to add those into the dictionary and for it to return the correct report access token with filtered data? 

 

Thanks, 

2 ACCEPTED SOLUTIONS

Accepted Solutions
Community Support Team
Community Support Team

Re: Implementing RLS on Embedded where report token is received by Azure AD REST call.

Hi @BaakWu,

 

If you use the Rest API, it could be like below. Please refer to #applying-user-and-role-to-an-embed-token.

{   
    "accessLevel": "View",
    "identities": [     
        {      
            "username": "EffectiveIdentity",
            "roles": [ "Role1", "Role2" ],
            "datasets": [ "fe0a1aeb-f6a4-4b27-a2d3-b5df3bb28bdc" ]
        }   
    ] 
} 

I tested it successfully with Postman.

 

Implementing RLS on Embedded where report token is received by Azure AD REST call.png 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Best Regards,

Dale

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

Re: Implementing RLS on Embedded where report token is received by Azure AD REST call.

Fixed,

 

I was confused because we were embedding the report through the Azure AD token, I am not sure how to implement RLS through the Azure AD token, like so.

 

 try
            {
                var tokenData = await _authenticationHandler.GetTokenDataAsync();

                using (var client = new PowerBIClient(new Uri(_powerBiSettings.MainAddress), tokenData.tokenCredentials))
                {
                    var report = await client.Reports.GetReportAsync(_powerBiSettings.GroupId, id.ToString());
                    
                    return new ReportDetail
                    {
                        Id = Guid.Parse(report.Id),
                        Name = report.Name,
                        EmbedUrl = report.EmbedUrl,
                        AccessToken = tokenData.accessToken
                    };
                }
            }

To fix this we just imbed the power BI report token instead with RLS identity.

 

            try
            {
                var tokenData = await _authenticationHandler.GetTokenDataAsync();

                using (var client = new PowerBIClient(new Uri(_powerBiSettings.MainAddress), tokenData.tokenCredentials))
                {
                    var report = await client.Reports.GetReportAsync(_powerBiSettings.GroupId, id.ToString());

                    var identity = new List<EffectiveIdentity>
                    {
                        new EffectiveIdentity("MasterUser", //TODO: Change this to use azure identity
                            roles: new List<string> {"User"},
                            datasets: new List<string> {report.DatasetId})
                    };

                    var generateTokenRequestParameters = new GenerateTokenRequest("view", null, identities: identity);

                    var tokenResponse = await client.Reports.GenerateTokenInGroupAsync(_powerBiSettings.GroupId, report.Id, generateTokenRequestParameters);

                    return new ReportDetail
                    {
                        Id = Guid.Parse(report.Id),
                        Name = report.Name,
                        EmbedUrl = report.EmbedUrl,
                        AccessToken = tokenResponse.Token
                    };
                }
            }

Be sure to set the token type to embed rather than AAD token in the Javascript config. 

 

Thanks for your help.

2 REPLIES 2
Community Support Team
Community Support Team

Re: Implementing RLS on Embedded where report token is received by Azure AD REST call.

Hi @BaakWu,

 

If you use the Rest API, it could be like below. Please refer to #applying-user-and-role-to-an-embed-token.

{   
    "accessLevel": "View",
    "identities": [     
        {      
            "username": "EffectiveIdentity",
            "roles": [ "Role1", "Role2" ],
            "datasets": [ "fe0a1aeb-f6a4-4b27-a2d3-b5df3bb28bdc" ]
        }   
    ] 
} 

I tested it successfully with Postman.

 

Implementing RLS on Embedded where report token is received by Azure AD REST call.png 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Best Regards,

Dale

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

Re: Implementing RLS on Embedded where report token is received by Azure AD REST call.

Fixed,

 

I was confused because we were embedding the report through the Azure AD token, I am not sure how to implement RLS through the Azure AD token, like so.

 

 try
            {
                var tokenData = await _authenticationHandler.GetTokenDataAsync();

                using (var client = new PowerBIClient(new Uri(_powerBiSettings.MainAddress), tokenData.tokenCredentials))
                {
                    var report = await client.Reports.GetReportAsync(_powerBiSettings.GroupId, id.ToString());
                    
                    return new ReportDetail
                    {
                        Id = Guid.Parse(report.Id),
                        Name = report.Name,
                        EmbedUrl = report.EmbedUrl,
                        AccessToken = tokenData.accessToken
                    };
                }
            }

To fix this we just imbed the power BI report token instead with RLS identity.

 

            try
            {
                var tokenData = await _authenticationHandler.GetTokenDataAsync();

                using (var client = new PowerBIClient(new Uri(_powerBiSettings.MainAddress), tokenData.tokenCredentials))
                {
                    var report = await client.Reports.GetReportAsync(_powerBiSettings.GroupId, id.ToString());

                    var identity = new List<EffectiveIdentity>
                    {
                        new EffectiveIdentity("MasterUser", //TODO: Change this to use azure identity
                            roles: new List<string> {"User"},
                            datasets: new List<string> {report.DatasetId})
                    };

                    var generateTokenRequestParameters = new GenerateTokenRequest("view", null, identities: identity);

                    var tokenResponse = await client.Reports.GenerateTokenInGroupAsync(_powerBiSettings.GroupId, report.Id, generateTokenRequestParameters);

                    return new ReportDetail
                    {
                        Id = Guid.Parse(report.Id),
                        Name = report.Name,
                        EmbedUrl = report.EmbedUrl,
                        AccessToken = tokenResponse.Token
                    };
                }
            }

Be sure to set the token type to embed rather than AAD token in the Javascript config. 

 

Thanks for your help.