Implementing custom authentication and authorization with Power BI Report Server

PowerBI is a the new Microsoft product for the reports design and deployment, composed by a server part that can be on cloud or On-Premise and PowerBI Desktop that is the client used to design the reports.

The Report Server (On-Premise) consists in web based interface to access and visualize the reports, protected by an authentication layer that need to be configured; we have two options about that, the first one is using our LDAP directory and enable the windows authentication; the second one is configure a custom authentication and implementing a piece of code (or use an existing one) that authenticate the user on the company directories.

In order to implementing the custom authentication, we have some steps to do about the code development and others about the server configuration.

Code development

We can start by downloading the Microsoft custom security sample project from GitHub.

In this project we’ll find a Logon.aspx page:

The page has the user and password fields and two buttons about the login and the user registration; for example we can change the look and feel of the page based on company brand.

We can put our custom authentication in the method invoked by the login button, in the Logon.aspx.cs file:

Instead of the VerifyPassword method we can put a call, for example, to an our web api authentication method and validate the credentials.

Another use case is call Power BI from and external application where the user is already authenticated; the user shouldn’t relogin on power bi and the report should appear without any authentication; we can manage this by passing, for example, the authentication token in the url of the report like this:

https://PBIhostname/ReportServer/logon.aspx?ReturnUrl=/ReportServer/localredirect?url=/Reports/powerbi/report.pbix&token=123

We are calling the logon page of PBI Report Server and we are passing the ReturnUrl parameter with the url of the report and the authentication token; now we can manage this token in the PageLoad event of the Logon.aspx.cs file:

The VerifyTokenAsync method deal with the token validation, for example by calling our Web Api; if the check will be ok, then the user will be automatically redirect to the report, otherwise a new login will be needed.

Once the page layout of the login page and the authentication layer are completed, we can configure PowerBI Report Server to use the custom authentication.

Server configuration

First, we have to copy the Logon.aspx page in the ReportServer sub directory, for example:

C:\Program Files\Microsoft Power BI Report Server\PBIRS\ReportServer

Next we have to copy the dll of the project into three subfolders:

  • ReportServer\bin
  • Portal
  • PowerBI

Then, edit the RSReportServer.config file located in the ReportServer folder; we have to modify the Authentication section like this:

<Authentication>
<AuthenticationTypes>
<Custom/>
</AuthenticationTypes>
<RSWindowsExtendedProtectionLevel>Off</RSWindowsExtendedProtectionLevel>
<RSWindowsExtendedProtectionScenario>Proxy</RSWindowsExtendedProtectionScenario>
<EnableAuthPersistence>true</EnableAuthPersistence>
</Authentication>

In the Security and Authentication elements, modify the Extension element like this:

<Extension Name="Forms" Type="Microsoft.Samples.ReportingServices.CustomSecurity.Authorization, Microsoft.Samples.ReportingServices.CustomSecurity" >

Now we have to modify the RSSrvPolicy.config file located in the ReportServer subfolder as well and add a new CodeGroup element:

<CodeGroup
class="UnionCodeGroup"
version="1"
Name="SecurityExtensionCodeGroup"
Description="Code group for the sample security extension"
PermissionSetName="FullTrust">
<IMembershipCondition
class="UrlMembershipCondition"
version="1"
Url="C:\Program Files\Microsoft Power BI Report Server\PBIRS\ReportServer\bin\Microsoft.Samples.ReportingServices.CustomSecurity.dll"/>
</CodeGroup>

The last file to edit is the Web.config file, we have to change the identity element:

<identity impersonate="false" />

The authentication element:

<authentication mode="Forms">
<forms loginUrl="logon.aspx" name="sqlAuthCookie" timeout="60" path="/"></forms>
</authentication>

The authorization element:

<authorization> 
<deny users="?" />
</authorization>

The trust element:

<trust level="Full" originUrl="" />

Now the configuration is completed and after a server restart, the custom authentication will be available.

With this project we are able to customize the authorization as well; we can intercept the events about the access to resources, folders, reports and apply our business logic.

Let’s look to the changes that we have to do.

Authorization

In the project there is an Authorization.cs file with some CheckAccess methods used by PowerBI Report Server to verify if a user is authorized to do a specific operation.

We can leverage these methods to implements our custom business logic; for example che custom authentication do not allow the use of groups, we don’t have an LDAP directory, so it’s impossible to it to resolve any group; but with a piece of code and these events we can solve the problem.

Suppose to store the user tokens used in previous chapter in a txt file; then we implement a method that accept two parameters, the username and the access entry to be check:

private bool IsMember(string username, string group)
{
var path = Directory.GetParent(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)).FullName + @"\ReportServer\tokens.txt";
if (File.Exists(path))
{
var tokens = JsonConvert.DeserializeObject<List<Token>>(File.ReadAllText(path));
var token = tokens.FirstOrDefault(t => t.Username.ToLower() == username.ToLower());
if (token != null)
{
var client = new HttpClient();
client.BaseAddress = new Uri(token.UrlServerSin);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Access_token);
var message = client.GetAsync(".....").Result;
if (message.StatusCode == HttpStatusCode.OK)
{
var groups = JsonConvert.DeserializeObject<string[]>(message.Content.ReadAsStringAsync().Result);
var enabled = groups.Any(g => g.ToLower() == group.ToLower());
return enabled;
}
}
}
 return false;
}

With the user token we can retrieve the user groups with our specific api and then check if the access entry is one of these.

Then, we can use this method in the events that we want to manage, for example the access of a folder:

With this change, when a user try to access to a folder where the security is defined with groups, the CheckAccess method is fired and with the custom method is checked if the user is member of a specific group.

We can do the same things for others components like reports.

Summary

The customization of the Power BI Report Server authentication allow to modify the layout of the login page, the business logic of the login phase (for example by calling a web api to login) and the business logic of the authorization mechanism.

With these elements we can customize the behaviour of the enviroment to fit to the comany requirements.

26 thoughts on “Implementing custom authentication and authorization with Power BI Report Server

Add yours

  1. Hello, first congratulations on the post, very well detailed and built. I have a question, see my scenario: I have a PHP intranet in the company that works only in the company environment behind a firewall.

    On this intranet I insert an IFRAME to incorporate some reports from the PBI Report Server, but always ask for a password that I defined as a local user.

    I really need that when accessing my page on the intranet, NO password was requested for the user. (I don’t need protection because the Firewall already does this and the data is not sensitive)

    Like

    1. Hello, you can use the custom authentication and in the Page_Load method of the logon page redirect the user to the report, or before that check a generic token authentication if you want to provide a minimal security.

      Like

  2. Hi! Thanks for answering!
    Redirecting the user directly to the report would be great, but there are several reports I have. Each area of the intranet carries a report.

    How would it be to check for generic token?
    Another question: do I need to compile something after changing it in “CustomSecuritySample” or just replace it in ReportServer Path?
    (I’m asking because I don’t know anything about ASP.NET or C #)

    Like

    1. Hi, as you can see in the post, you have to call the report with an url like this one:
      https://PBIhostname/ReportServer/logon.aspx?ReturnUrl=/ReportServer/localredirect?url=/Reports/powerbi/report.pbix&token=123

      where your report is report.pbix and the token is a generic token.
      In the page_load event of the login page you can retrieve the token with Request.QueryString[“token”], if it’s ok you have to call FormsAuthentication.Redirect…
      that will redirect automatically the navigation to the relative path specified in the url parameter of the query string.

      Like

  3. Ciao Mirko,
    prima di tutto grazie per il tuo aritcolo molto interessante.
    Nella nostra azienda abbiamo Power BI report server on premise e vorremmo usare un’autentifazione via l’LDAP aziendale.

    Con metodo descritto nel tuo articolo te é possibile?

    La gestione degli accessi ai vari reports ai vari utilizzatori é fattibile?

    Grazie e buona giornata

    Like

    1. Ciao Andrea, si nell’esperienza che ho avuto io in un’azienda cliente abbiamo prima impostato l’autenticazione windows con accesso alla active directory aziendale. Successivamente, essendo l’esigenza quella di autenticarsi su più directory LDAP siamo passati all’autenticazione custom, quindi una dll che gestisce la scansione delle varie directory aziendali. Nel vostro caso probabilmente sarebbe sufficiente l’autenticazione windows.

      Like

  4. Hi Mirko, we’ve been following your post to implement custom security on Power Bi. We integrated it with Identity Server 4 successfully. The problem we are facing now is Authorization. Our idea was to verify if user have permission to view report by calling our API from CheckAccess method. API would receive user ID and report GUID and return true or false based on what we have in DB related to user/report permissions. Currently we cannot find Report GUID user is trying to see in CheckAccess. What are we missing? Thanks a lot

    Like

  5. I have configured the Power BI Report Server for custom authentication. When we login with the custom user we get the following error. Request your help in this regard and let us know how to associate security roles to custom users

    -William Stanaland

    Like

  6. Ciao Mirko,
    come prima cosa complimenti per l’articolo, veramente chiaro.
    Ho una domanda, secondo te è possibile eseguire un’autenticazione con Identity Server 4?

    Like

    1. Ciao Tony, grazie, puoi fare qualsiasi tipo di autenticazione se nel metodo VerifyPassword chiami un tuo ws che esegue la logica di autenticazione. Nel ws esposto dovresti implementare l’autenticazione con Identity Server 4.

      Like

  7. Hi, Have followed the steps but the page redirection does not happen and also report server goes inaccessible (Internal Server Error 500), but confirmed that report service is up and running. In your post you said about Authentication Token to access pbi dashboard from report server.

    Like

  8. Hello, could you possibly expand on this statement: “for example we can change the look and feel of the page based on company brand.” – perhaps with some code/markup samples of how to include styling and/or a company logo on the PowerBI login page?

    Like

      1. I understand how to write html and CSS to style a web page. I was hoping you would have a concrete example specific to Power BI login. The reason I asked the question is because we have been trying to add styling and images to the login.aspx page and it isn’t working. I do not have a local instance of Power BI running on my machine. To compensate/simulate, I created a simple ASP.Net web app on my local machine. When I run login.aspx in that local web app, the styling and images display as desired. However, when we deploy the login.aspx page and the accompanying images and styling to a real Power BI environment, the styling and images are not displaying, leaving just broken image placeholders and no CSS. I think it might have to do with how Power BI is treating the images and stylesheets as protected resources, and not serving them to the browser because the user has not yet been authenticated, I’ve been Googling how to add branding to Power BI and/or SSRS login pages for quite some time, and have not found any actual documented solutions for this. So I’m wondering if it’s actually possible.

        Like

  9. Hello,

    Nice Tutorial, we’ve implemented a custom authentification on Power BI report Server by Calling a web API, however after session time out, PBIRS propose again the Windows authentification.

    How can handle this part ? (we want to redirect the user to login page after session timeout)

    Like

  10. Hello,
    Please help us same issue, Not able to call this below getting build errors, and don’t knw how to validate TOKEN from the URL pass token from Embedded in custom Authentication asp.net customization code.

    var result = AuthenticationUtilities.VerifyTokenAsync(Request.QueryString[“token”])

    Please help us more clear code

    Like

    1. Hi, you need to validate the token with your custom logic, in my case this is the code:

      internal static string VerifyTokenAsync(string token, Label lblMessage)
      {
      try
      {
      var uri = ConfigurationManager.AppSettings[“UriServer”];
      HttpResponseMessage message = null;
      string server = null;
      var client = new HttpClient();
      client.BaseAddress = new Uri(uri);
      client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, token);
      message = client.GetAsync(“api/security/GetCurrentUsername”).Result;
      client.Dispose();

      if (message?.StatusCode != HttpStatusCode.OK)
      return null;

      var result = message.Content.ReadAsStringAsync().Result;
      var user = JsonConvert.DeserializeObject(result);

      return user;
      }
      catch (Exception ex)
      {
      lblMessage.Text = string.Format(CultureInfo.InvariantCulture, ex.Message);
      return null;
      }
      }

      Like

  11. Hello
    Thanks a lot for this very helpfull post !
    I have succesfully implemented the custom security on my PBIRS server.
    But I can’t deploy any Power BI dashboard from Power BI Desktop RS.
    When I try to connect to the report server from the PBI Desktop (using http://MyServer/Reports ), I get an Unexpected Errror Occured. Looking at the RSPortal_xxx.log, I have a 401 error.

    I have tried to put http://MyServer/ReportServer/logon.aspx?ReturnUrl=/ReportServer/localredirect?url=/Reports&token=123 but I get a “We couldn’t find a Power BI Report Server at this adress”

    Any idea ?

    Thanks in advance
    Franck

    Like

Leave a Reply to Hitesh Vyas Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: