
Dans les projets récents, il est vite apparu que les données seules ne suffisent pas : leur vraie valeur se révèle lorsqu’elles peuvent être transformées rapidement en informations exploitables. Power BI s’est imposé comme un allié précieux pour y parvenir, en permettant de visualiser, analyser et partager les données de façon fluide et intuitive.
Mais une question s’est posée naturellement lors de nos développements : comment apporter cette intelligence directement dans les applications que nos utilisateurs utilisent au quotidien, sans qu’ils aient à basculer vers un outil séparé ?

Aujourd’hui, il ne suffit plus de produire des rapports isolés. L’objectif est d’embarquer l’analyse de données là où les utilisateurs se trouvent, directement au cœur des applications web. C’est là que Power BI Embedded révèle tout son potentiel.
Dans notre expérience, Power BI Embedded a permis de prolonger la puissance des rapports classiques en les intégrant de manière native et transparente dans nos plateformes. Résultat : l’intelligence décisionnelle devient accessible directement aux utilisateurs finaux, avec une expérience homogène et parfaitement intégrée.
Cet article sera purement technique : il détaille concrètement comment exploiter Power BI Embedded pour intégrer des fonctionnalités analytiques dans vos applications, avec des conseils pratiques basés sur notre retour d’expérience.
Power BI Embedded est une solution Azure qui permet d'intégrer des rapports, tableaux de bord et visualisations Power BI directement dans des applications web ou mobiles. Contrairement à Power BI Service, qui est conçu pour être utilisé comme plateforme autonome, Embedded offre une expérience transparente où l'analytique devient une fonctionnalité native de l'application hôte. Les utilisateurs finaux accèdent ainsi aux données sans quitter leur environnement de travail habituel.
L'intégration repose sur une architecture en trois couches. Tout d'abord, les rapports Power BI sont publiés sur un espace de travail dédié dans Power BI Service. Ensuite, l'application backend génère un token d'authentification (embed token) via les API REST de Power BI, garantissant un accès sécurisé et contrôlé. Enfin, le frontend utilise le SDK JavaScript de Power BI pour afficher les rapports de manière interactive dans l'interface utilisateur, offrant ainsi une expérience fluide et réactive.

Pour bien comprendre le mécanisme, il est essentiel de distinguer deux types de jetons (tokens) qui interviennent dans le processus :
Point de sécurité important : Seul l'Embed Token doit transiter vers le Frontend. L'Access Token, qui donne des droits d'administration sur vos ressources, doit rester exclusivement sur votre serveur Backend.
L'un des principaux atouts de Power BI Embedded réside dans sa capacité à personnaliser entièrement l'expérience utilisateur. Les entreprises peuvent adapter l'apparence des rapports à leur charte graphique, masquer certaines fonctionnalités ou définir des filtres dynamiques selon le profil de l'utilisateur connecté. Cette approche permet également de centraliser la gestion des données tout en distribuant l'analyse au plus près des besoins métier.
La sécurité constitue un pilier essentiel de Power BI Embedded. Grâce à la sécurité au niveau des lignes (Row-Level Security - RLS), il est possible de filtrer les données affichées en fonction des droits de l'utilisateur. Les tokens d'intégration sont temporaires et limités dans leur portée, ce qui renforce la protection des informations sensibles. L'ensemble du processus d'authentification et d'autorisation peut être géré via Azure Active Directory, garantissant une conformité avec les politiques de sécurité de l'entreprise.
// Full code in my github repo
Côté prérequis techniques, vous aurez besoin d’un espace de travail Power BI avec au moins un rapport publié, d’une inscription d’application dans Azure AD (avec les permissions Power BI), d’un projet spring boot 3.X et d'un projet Angular.
N.B : Veuillez vous référer à la documentation de Microsoft ajoutée en fin d’article pour configurer votre projet Power BI.
Le backend joue le rôle de gardien sécurisé : il s'authentifie auprès d'Azure AD, récupère les informations du rapport via l'API Power BI REST, génère un Embed Token sécurisé et le renvoie au frontend.
Dépendance Maven
A utiliser Microsoft Authentication Library for Java (MSAL4J) qui permet d’obtenir le token Azure AD (oauth2) pour appeler l’API Power BI.
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>msal4j</artifactId>
<version>1.16.0</version>
</dependency>Config
Deux méthodes d'authentification sont possibles :

N.B : Pourquoi le "Master User" est déconseillé ?
Si vous utilisez un Master User et que l'administrateur Azure de votre entreprise active l'authentification multifacteur (MFA) par sécurité, votre application Spring Boot s'arrêtera de fonctionner car elle ne pourra pas "valider" le code reçu (par SMS ou application).
Pour remédier à ce problème, nous vous recommandons d’opter pour le ServicePrincipal, le fichier yaml doit être rempli par ces identifiants comme suit :
powerbi:
tenant-id: YOUR_TENANT_ID
client-id: YOUR_CLIENT_ID
client-secret: YOUR_CLIENT_SECRET
workspace-id: YOUR_WORKSPACE_ID
report-id: YOUR_REPORT_ID
azure:
authority-url: https://login.microsoftonline.com/
scope-url: https://analysis.windows.net/powerbi/api
powerbi-api-url: https://api.powerbi.com/v1.0/myorgNote importante sur la sécurité des secrets
Dans cet article, nous avons utilisé des identifiants en clair dans le fichier application.yml à des fins de simplification pédagogique, afin de rendre la configuration initiale plus facile à appréhender pour le lecteur. Cependant, et en conditions réelles, ne stockez jamais vos identifiants (Client ID, Secret, Tenant ID) en clair dans vos fichiers de configuration car cela expose vos secrets lors du versionnement sur Git.
La solution recommandée : utilisez des variables d'environnement.
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Configuration
public class Config {
public final boolean DEBUG = false;
public final String authenticationType = "ServicePrincipal";
@Value("${powerbi.workspace-id}")
private String workspaceId;
@Value("${powerbi.client-secret}")
private String clientSecret;
@Value("${powerbi.client-id}")
private String clientId;
@Value("${powerbi.tenant-id}")
private String tenantId;
@Value("${powerbi.report-id}")
public String reportId;
@Value("${azure.authority-url}")
private String authorityUrl;
@Value("${azure.scope-url}")
private String scopeBase;
@Value("${azure.powerbi-api-url")
private String powerbiApiUrl;
}Créer une classe embedded.
public class Embedded {
private String token;
private String tokenId;
private String reportId;
private String groupeId;
}Service pour obtenir un Access Token Azure AD
public String getAccessTokenvis() throws Exception {
ConfidentialClientApplication app = ConfidentialClientApplication
.builder(
config.getClientId(),
ClientCredentialFactory.createFromSecret(config.getClientSecret())
)
.authority(config.getAuthorityUrl() + config.getTenantId())
.build();
ClientCredentialParameters params = ClientCredentialParameters
.builder(Collections.singleton(config.getScopeBase() + "/.default"))
.build();
IAuthenticationResult result = app.acquireToken(params).get();
return result.accessToken();
}Service Power BI : génération du Embed Token.
@Component
@AllArgsConstructor
@Slf4j
public class PowerBIService {
private final Config config;
static final Logger logger = LoggerFactory.getLogger(PowerBIService.class);
private AzureADService azureADTokenService;
public Embedded generateEmbedToken() throws Exception {
logger.info("Start Service : Generating Embed Token");
String accessToken = azureADTokenService.getAccessTokenvis();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(accessToken);
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("accessLevel", "View");
requestBody.put("identities", new String[]{});
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> entity = new HttpEntity<>(new ObjectMapper()
.writeValueAsString(requestBody), headers);
String url = String.format(
"https://api.powerbi.com/v1.0/myorg/groups/%s/reports/%s/GenerateToken",
config.getWorkspaceId(),
config.getReportId()
);
ResponseEntity<String> response = restTemplate.postForEntity(url, entity,
String.class);
Embedded responseObject = new Embedded();
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(response.getBody());
responseObject.setToken(jsonNode.get("token").asText());
responseObject.setTokenId(jsonNode.get("tokenId").asText());
responseObject.setReportId(config.getReportId());
responseObject.setGroupeId(config.getWorkspaceId());
logger.info("End Service : Generating Embed Token");
return responseObject;
}
}
Mettre en place un REST Controller pour exposer le token à Angular.
@AllArgsConstructor
@RestController
@Slf4j
public class PowerBIController {
private final PowerBIService powerBIEmbedService;
@GetMapping("/embedToken")
public Embedded getEmbedToken() {
try {
return powerBIEmbedService.generateEmbedToken();
} catch (Exception e) {
e.printStackTrace();
return new Embedded();
}
}
}Configuration :
installer le SDK JavaScript officiel permettant d’intégrer des rapports Power BI Embedded dans votre frontend Angular.
npm install powerbi-client-angular powerbi-client --saveCréez un composant dédié à l'affichage de votre rapport.
ng generate component powerbi-reportCréer une classe EmbededModel qui contient comme attributs token et reportId.

Quelques illustrations du code :
ici notre service va faire l’appel à notre api exposée en backend.
export class EmbededReportService {
private embededReport = environment.baseUrl + 'embedToken' ;
constructor(private httpClient: HttpClient) {
}
getReport(): Observable<EmbededModel> {
const options = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
};
return this.httpClient.get<EmbededModel>(this.embededReport, options);
}
}Ajouter le composant dans powerbi-report.component.html.
<div>
@if (isConfigReady) {
<powerbi-report
[embedConfig]="reportConfig"
[cssClassName]="'reportClass'"
[eventHandlers]="eventHandlersMap"
></powerbi-report>
}
</div>Ajouter ces importations dans le fichier ts.
import {Component, OnInit, ViewChild} from '@angular/core';
import {IReportEmbedConfiguration, models, service} from 'powerbi-client';
import {EmbededReportService} from '../services/EmbededReportService';
import {PowerBIEmbedModule, PowerBIReportEmbedComponent} from 'powerbi-client-angular';
import { ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'Ajouter les filtres sur les tables.
targetTable et targetColumn présentent respectivement le nom de la dimension dans le dataset de powerBI et la colonne sur laquelle nous souhaitons appliquer le filtre.
Dans notre cas, au lieu de configurer la RLS dans Power BI Desktop, le filtrage se fait directement depuis Angular. L'attribut values permet de rendre ce filtrage dynamique, il reçoit la valeur du profil de l'utilisateur connecté (sa région, son équipe, son ID,etc.) et l'applique comme filtre au rapport au moment du chargement.
Le flux en 3 étapes :
À noter que la gestion du profil côté backend n'est pas abordée ici, car elle dépend de l'architecture propre à votre projet.
basicFilter: models.IBasicFilter = {
$schema: 'http://powerbi.com/product/schema#basic',
target: {
table: this.targetTable,
column: this.targetColumn
},
operator: 'In',
values: [], // fill in the value
filterType: models.FilterType.Basic,
requireSingleSelection: true,
};Cette section définit la configuration du rapport. Elle prend en paramètres le type du rapport, l'URL et le token d'intégration (embed), les filtres dynamiques à appliquer, ainsi que quelques paramètres de mise en forme comme l'affichage du volet de navigation ou du panneau de filtres.
reportConfig: IReportEmbedConfiguration = {
type: 'report',
embedUrl: '',
tokenType: models.TokenType.Embed,
accessToken: '',
permissions: models.Permissions.All,
settings: {
filterPaneEnabled: false,
panes: {
pageNavigation: {
visible: false,
position: models.PageNavigationPosition.Left
}
},
navContentPaneEnabled: false,
customLayout: {
displayOption: models.DisplayOption.FitToWidth
}
}, filters: [this.basicFilter]
};
Cette partie définit une méthode qui se charge de récupérer la configuration d'intégration (embed config) générée par notre API backend Spring Boot.
embedReport() {
this.embededReportService.getReport().subscribe({
next: (data) => {
this.reportConfig = {
...this.reportConfig,
id: data.reportId,
accessToken: data.token,
embedUrl: `https://app.powerbi.com/reportEmbed?reportId=${data.reportId}&groupId=${data.groupId}`,
filters: [this.basicFilter]
};
this.isConfigReady = true;
this.cdr.markForCheck();
},
error: (err) => console.error('Error fetching token', err)
});
}Enfin, cette méthode est appelée dès le chargement du composant via ngOnInit, mais vous êtes libre de définir votre propre déclencheur selon vos besoins.
N.B. : vous devez ajouter des eventsHandlers comme mentionné ci-dessous,notamment pour suivre l’état de chargement du rapport. Cela permet, par exemple, d’afficher un loader pendant le chargement et de réagir une fois que le rapport est prêt.
eventHandlersMap = new Map<string, (event?: service.ICustomEvent<any>) => void>([
['loaded', () => console.log('Report loaded')],
['rendered', () => console.log('Report rendered')],
['error', (event) => console.log(event?.detail)]
]);Dans notre expérience, Power BI Embedded s’est rapidement imposé comme une solution très efficace pour intégrer l’analytique directement dans nos applications web . Au lieu de proposer des tableaux de bord séparés, nous avons pu offrir une expérience fluide, totalement intégrée et alignée avec le design de nos applications.
Ce qui nous a particulièrement marqués, c’est la flexibilité de la solution. Grâce à Azure, à l’API REST et au SDK JavaScript, nous avons pu construire des expériences analytiques avancées tout en gardant un contrôle total sur l’accès, la sécurité et l’intégration côté front-end.
Au final, cette approche nous a permis d’aller plus vite, de réduire la complexité technique et surtout de rendre la donnée accessible directement dans les outils utilisés au quotidien. Cela a clairement changé notre façon de livrer des fonctionnalités liées à la donnée.
Pour approfondir les sujets abordés dans cet article, voici quelques ressources recommandées :
-> Documentation officielle Microsoft Power BI Embedded
https://learn.microsoft.com/en-us/power-bi/developer/embedded/embedded-analytics-power-bi
https://learn.microsoft.com/en-us/power-bi/developer/embedded/embed-sample-for-customers?tabs=java
-> Github Repository
https://github.com/xelops-technology/PowerBi-Embedded-Front-End
https://github.com/xelops-technology/PowerBi-Embedded-Back-End