holyshilo111
holyshilo111

Reputation: 133

Power BI Embedded for customers - Creating embeded URL

I'm embedding a Power BI report on a "Embed for customer" manner and authenticating via service account. I have managed to get the embed token for a single report and a single workspace using Microsoft guides.

The issue comes when making a POST request to https://api.powerbi.com/v1.0/myorg/groups/{workspace_id}/reports/{report_id}. I get a 403 error.

Also, note that I am using Django and the final purpose is to process everything on the backend and just send a URL to the front end to put inside an iframe.

This is my Django View:

from django.shortcuts import render
from django.views.generic import TemplateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import JsonResponse
from django.views import View
from django.shortcuts import get_object_or_404
from .models import Dashboard, ReportConfig, EmbedConfig, EmbedTokenRequestBody
from .serializer import DashboardSerializer
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from powerbi.aadservice import AadService

import requests
import json

class DashboardView(viewsets.ModelViewSet):
    serializer_class = DashboardSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        # Retrieve the user's groups
        user = self.request.user
        user_groups = user.groups.all()

        # Filter the dashboards based on group membership
        queryset = Dashboard.objects.filter(group__in=user_groups)

        return queryset

class PbiEmbedService(View):
    def get(self, request, workspace_id, report_id, additional_dataset_id=None):
        '''Get embed params for a report and a workspace'''
        report_url = f'https://api.powerbi.com/v1.0/myorg/groups/{workspace_id}/reports/{report_id}'
        api_response = requests.get(report_url, headers=self.get_request_header())

        if api_response.status_code != 200:
            return JsonResponse(
                {
                    'error': f'Error while retrieving Embed URL\n{api_response.reason}:\t{api_response.text}\nRequestId:\t{api_response.headers.get("RequestId")}'
                },
                status=api_response.status_code,
            )

        api_response = json.loads(api_response.text)
        report = ReportConfig(api_response['id'], api_response['name'], api_response['embedUrl'])
        dataset_ids = [api_response['datasetId']]

        # Append additional dataset to the list to achieve dynamic binding later
        if additional_dataset_id is not None:
            dataset_ids.append(additional_dataset_id)

        embed_token = self.get_embed_token_for_single_report_single_workspace(report_id, dataset_ids, workspace_id)
        embed_config = EmbedConfig(embed_token.tokenId, embed_token.token, embed_token.tokenExpiry, [report.__dict__])

        parsed_token = (embed_config.__dict__)
        access_token = parsed_token['token']

        #Here's where the issue starts
        embed_url = f'https://api.powerbi.com/v1.0/myorg/groups/{workspace_id}/reports/{report_id}'
        headers = {'Authorization': f'Bearer {access_token}'}

        response = requests.post(embed_url, headers=headers)
        print(response)

        return JsonResponse(embed_config.__dict__)



    def get_request_header(self):
        '''Get Power BI API request header'''
        return {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + AadService.get_access_token()}

    def get_embed_token_for_single_report_single_workspace(self, report_id, dataset_ids, target_workspace_id=None):
        '''Get Embed token for single report, multiple datasets, and an optional target workspace

        Args:
            report_id (str): Report Id
            dataset_ids (list): Dataset Ids
            target_workspace_id (str, optional): Workspace Id. Defaults to None.

        Returns:
            EmbedToken: Embed token
        '''

        request_body = EmbedTokenRequestBody()

        for dataset_id in dataset_ids:
            request_body.datasets.append({'id': dataset_id})

        request_body.reports.append({'id': report_id})

        if target_workspace_id is not None:
            request_body.targetWorkspaces.append({'id': target_workspace_id})

        # Generate Embed token for multiple workspaces, datasets, and reports. Refer https://aka.ms/MultiResourceEmbedToken
        embed_token_api = 'https://api.powerbi.com/v1.0/myorg/GenerateToken'
        api_response = requests.post(embed_token_api, data=json.dumps(request_body.__dict__), headers=self.get_request_header())

        if api_response.status_code != 200:
            return JsonResponse(
                {
                    'error': f'Error while retrieving Embed URL\n{api_response.reason}:\t{api_response.text}\nRequestId:\t{api_response.headers.get("RequestId")}'
                },
                status=api_response.status_code,
            )

        api_response = json.loads(api_response.text)
        embed_token = EmbedConfig(api_response['tokenId'], api_response['token'], api_response['expiration'], [])

        return embed_token

At the moment, what I got is:

{
    "tokenId": "REDACTED",
    "token": "REDACTED",
    "tokenExpiry": "2023-07-12T22:47:42Z",
    "reports": [
        {
            "id": "REDACTED",
            "name": "Supply Chain Sample",
            "embedUrl": "https://app.powerbi.com/reportEmbed?reportId=REDACTEDb&groupId=REDACTED&w=2&config=REDACTED"
        }
    ]
}

Upvotes: 0

Views: 1740

Answers (1)

Kotana Sai
Kotana Sai

Reputation: 1810

For Getting Embed URL, you need to send the GET request and not the POST request.

Refer Get Report In Group Documentation for more details.

Upvotes: 0

Related Questions