Con el plan de licencias de Power BI, para poder compartir un report publicado en Power BI Online con otros usuarios para que puedan verlo e interactuar con él, tendríamos varias opciones:

  • Que, tanto el usuario que hace la publicación, como los usuarios con los que se quiere compartir tengan licencia Pro de Power BI.
  • Tener Power BI Premium, en cuyo caso los usuarios con los que se comparte para lectura no necesitarían tener licencia Pro.
  • Publicar en web, pero cualquier usuario en Internet conocedor de la URL y sin autenticar podría ver el report: https://powerbi.microsoft.com/en-us/documentation/powerbi-service-publish-to-web/.
  • Utilizar el API REST de Power BI para incluir el report en un componente web. De esta forma, solo se necesitaría un usuario Pro que se utilizaría como “cuenta de servicio” para obtener el report.

En este post voy a contar la alternativa que tenemos mediante el API REST de Power BI. De esta forma, vamos a poder publicar un report dentro de nuestra intranet y que lo puedan ver usuarios que no tienen licencia Pro; o que, directamente, no tienen usuario de Power BI. A continuación vemos los pasos.

En primer lugar, tenemos que registrar una aplicación en Azure Active Directory (Azure AD) desde el portal de Azure con un usuario con permisos de administración en el tenant. Los pasos para ello:

  1. Desde la ventana de registro de aplicaciones, hacemos clic en el botón de nuevo registro de aplicación:
  2. En el formulario de creación, indicamos los siguientes datos y hacemos clic en el botón de crear:
    • El nombre de la aplicación.
    • El tipo de aplicación, que ha de ser “Nativa”; ya que la queremos para obtener contenido para usuarios que no se van a autenticar en Power BI.
    • URL a la que redireccionar tras una solicitud de autenticación (esta propiedad no la vamos a utilizar en nuestro ejemplo, ya que proporcionaremos las credenciales mediante código; pero sí la necesitaríamos si hiciéramos una redirección a la página de login para introducir las credenciales manualmente).
  3. Una vez creada la aplicación, prestamos especial atención al identificador, ya que lo necesitaremos en nuestro código para autenticar al usuario que solicitará el report:

En segundo lugar, una vez registrada la aplicación, hay que asignarle permisos para que pueda adquirir los mismos permisos que la cuenta de usuario bajo la que se ejecuta. Los pasos para ello:

  1. Desde la ventana de registros de aplicaciones, buscamos la aplicación y la seleccionamos:
  2. En el menú de configuración, seleccionamos la opción de permisos necesarios:
  3. En la ventana de permisos, seleccionamos el API de Windows Azure AD:
  4. En la ventana de habilitar acceso, seleccionamos el permiso “Access the directory as the signed-in user”, y hacemos clic en el botón de guardar:

También tenemos que asignar a la aplicación permisos en el servicio de Power BI:

  1. En la ventana de permisos de la aplicación, hacemos clic en el botón de agregar:
  2. A continuación, seleccionamos el API “Power BI Service” y hacemos clic en el botón de seleccionar:
  3. En la ventana de habilitar acceso, seleccionamos todos los permisos (puede que sea necesario ir de uno en uno para que se habilite el botón de seleccionar):
  4. Finalmente, aceptamos toda la configuración de permisos que hemos hecho para el API:
  5. En la ventana de permisos, hacemos clic en conceder permisos para conceder a todos los usuarios del directorio los permisos de la aplicación:

En este punto ya tenemos todo lo que necesitamos para desarrollar nuestro componente web que invoque el API REST de Power BI para obtener el report y mostrarlo. A continuación vemos los detalles.

En primer lugar, necesitamos obtener un token de autorización de Azure AD para poder acceder a los recursos de Power BI:

string aadLogin = "https://login.microsoftonline.com/{0}";
string tenant = "contoso.onmicrosoft.com";
string authority = String.Format(CultureInfo.InvariantCulture, aadLogin, tenant);
AuthenticationContext authContext = new AuthenticationContext(authority);

string resourceId = "https://analysis.windows.net/powerbi/api";
string clientId = " a7c98fc1-098b-4561-b0c6-a9939f79f563";
string pbiUsername = "pbiUser@contoso.onmicrosoft.com";
string pbiPassword = "xxxxxxxx";

AuthenticationResult result = authContext.AcquireToken(resourceId, clientId, new UserCredential(pbiUsername, pbiPassword));

accessToken.Value = result.AccessToken;

En este fragmento de código podemos destacar lo siguiente:

  • La variable tenant hace referencia al tenant de Azure AD al que vamos a solicitar el token.
  • resourceId identifica el recurso para el que vamos a solicitar la autorización. En este caso, el id “https://analysis.windows.net/powerbi/api” identifica el API de Power BI.
  • clientId es el identificador de la aplicación que registramos en Azure AD en el paso 1.
  • pbiUsername y pbiPassword son las credenciales del usuario para que el que se va a solicitar el token. Este usuario ha de existir en el tenant de Azure AD, y ha de tener licencia Pro de Power BI para poder obtener el report.
  • accessToken es un campo hidden que hemos utilizado en nuestro aspx para almacenar el token y poder obtenerlo posteriormente mediante JavaScript.

Una vez que tenemos el token de autorización, ya podemos solicitar el report:

En primer lugar, definimos las clases para deserializar la respuesta con los reports (con algunas de las propiedades que obtenemos):

public class PBIReports
{
    public PBIReport[] value { get; set; }
}

public class PBIReport
{
    public string id { get; set; }
    public string name { get; set; }
    public string webUrl { get; set; }
    public string embedUrl { get; set; }
}

En este fragmento de código:

  • En id se guardará el GUID del report.
  • En name se guardará el nombre del report.
  • En webUrl se guardará la URL del report.
  • En embedUrl se guardará la URL embebida del report.

Realizamos la solicitud y procesamos la respuesta:

string baseUriAPI = "https://api.powerbi.com/v1.0/myorg";
WebRequest request = WebRequest.Create(String.Format("{0}/reports", baseUriAPI)) as HttpWebRequest;

request.Method = "GET";
request.ContentLength = 0;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.Value));

using (var response = request.GetResponse() as HttpWebResponse)
{
    using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
    {
        PBIReports reports = JsonConvert.DeserializeObject<PBIReports>(reader.ReadToEnd());
        if (reports.value.Length > 0)
        {
            var report = reports.value[0];
            LblEmbedUrl.Text = report.embedUrl;
            LblReportId.Text = report.id;
            LblReportName.Text = report.name;
        }
    }
}

En este fragmento de código:

  • baseUriAPI contiene la URL del API de Power BI y, en la siguiente línea le concatenamos el nombre de la operación que vamos a utilizar. En este caso “reports” porque queremos obtener los reports del usuario que los solicita (es decir, los de su workspace). Si quisiéramos obtener los de otro workspace tendríamos que utilizar “groups”. Podéis encontrar información más detallada de las distintas operaciones que hay en el siguiente enlace: https://msdn.microsoft.com/en-us/library/mt147898.aspx. También tenéis un enlace en el que, además, podéis probar algunas de las operaciones: http://docs.powerbi.apiary.io.
  • Incluimos el token obtenido en el paso 4.a en una cabecera “Authorization”.
  • Procesamos la respuesta obtenida. Dado que la operación “reports” nos devuelve todas los reports del usuario, en este caso nos quedamos con los datos (identificador, nombre y URL) del primero de ellos y los guardamos en labels de aspx para obtenerlos después mediante JavaScript. De esta forma, ya tenemos toda la información que necesitamos del report para incrustarlo en nuestro componente web. En nuestro ejemplo, lo vamos a incrustar en un elemento div y, para ello, vamos a utilizar la librería de JavaScript “powerbi-client”. Para instalar esta librería tenemos un paquete de npm y el paquete de Nuget “Microsoft.PowerBI.JavaScript”.

Y, por último, lo que sería nuestro aspx:

<div>
    <script type="text/javascript" src="scripts/powerbi.js"></script>
    <script type="text/javascript">
        window.onload = function () {
            var accessToken = document.getElementById('accessToken').value;
            if (!accessToken || accessToken == "") {
                return;
            }

            var embedUrl = document.getElementById('LblEmbedUrl').innerText;
            var reportId = document.getElementById('LblReportId').innerText;

            var models = window['powerbi-client'].models;
            var config = {
                type: 'report',
                tokenType: models.TokenType.Aad,
                accessToken: accessToken,
                embedUrl: embedUrl,
                id: reportId
            };

            var reportContainer = document.getElementById('reportContainer');
            var report = powerbi.embed(reportContainer, config);
        };

    </script>

    <asp:HiddenField ID="accessToken" runat="server" />

    <h1>Demo Power BI Embed Report</h1>
    <div>
        Report Name:
        <asp:Label ID="LblReportName" runat="server"></asp:Label>
    </div>
    <div>
        Report Id:
        <asp:Label ID="LblReportId" runat="server"></asp:Label>
    </div>
    <div>
        Report Embed URL:
        <asp:Label ID="LblEmbedUrl" runat="server"></asp:Label>
    </div>
    <div>
        <div id="reportContainer" style="width:900px; height:500px"></div>
    </div>
</div>

En este fragmento de código:

  • Tenemos las labels en las que vamos a mostrar la información del report: LblReportId con el GUID, LblReportName con el nombre y LblEmbedUrl con la URL embebida.
  • El div en el que vamos a incrustar el report: reportContainer.
  • El campo hidden accessToken, en el que almacenamos el token de autorización en el paso 4.a.
  • El código JavaScript en el que utilizamos la librería “powerbi-client” para incrustar el report en el div reportContainer. De este fragmento de código lo más importante es la variable config y la función embed. Como se puede ver, la variable config es un objeto que describe qué queremos incrustar y cómo lo queremos incrustar, para después pasárselo a la función embed junto con el elemento html en el que lo queremos incrustar (y esta función ya se encarga de ello). Por tanto, dentro de la variable config encontramos:
    • El tipo de contenido a incrustar, que en este caso es un report; por lo que indicamos el literal “report”.
    • El tipo de token que proporcionamos. En este caso es Aad, ya que utilizamos una cuenta de usuario de Power BI para obtener el token. Si lo estuviéramos generando con el método GenerateToken del API REST de Power BI, el tipo sería Embed.
    • El token de autorización.
    • La URL embebida del report.
    • El GUID del report.

Tenéis información más detallada de esta librería en el siguiente enlace: https://github.com/Microsoft/PowerBI-JavaScript/wiki.

Ahora ya, si ejecutamos nuestro código, podremos ver el report incrustado en nuestro componente web:

Imagen de ejemplo de un report incrustado en un componente webImagen de ejemplo de un report incrustado en un componente web

Y hasta aquí el post sobre cómo compartir un report con usuarios que no tienen licencia Pro de Power BI. Podéis bajar una copia del código de ejemplo en el siguiente enlace: https://github.com/lolijimenez/PowerBIPocShareWithNoPBIUsers.

Para este ejemplo, solo hemos necesitado una cuenta de usuario con licencia Pro que utilizamos como cuenta de servicio. No obstante, si quisiéramos jugar con permisos para que solo determinados usuarios puedan ver partes del report, tendríamos que tener diferentes cuentas de servicio.