1 min read
Power BI Embed for Organization: Internal Analytics Integration
I wrote “Power BI Embed for Organization: Internal Analytics Integration” to share practical, production-minded guidance on this topic.
When to Use
use_cases:
- Internal portals
- SharePoint integration
- Custom line-of-business apps
- Teams applications
requirements:
- Users have Power BI Pro or Premium Per User licenses
- Azure AD authentication
- Report sharing permissions
Implementation
Azure AD App Registration
# Register application
az ad app create \
--display-name "Internal-PowerBI-App" \
--reply-urls "https://internalapp.company.com/callback" \
--available-to-other-tenants false
React with MSAL
import { useMsal } from "@azure/msal-react";
import { PowerBIEmbed } from 'powerbi-client-react';
import { models } from 'powerbi-client';
function InternalDashboard() {
const { instance, accounts } = useMsal();
const [accessToken, setAccessToken] = useState(null);
useEffect(() => {
async function acquireToken() {
const request = {
scopes: ["https://analysis.windows.net/powerbi/api/.default"],
account: accounts[0]
};
try {
const response = await instance.acquireTokenSilent(request);
setAccessToken(response.accessToken);
} catch (error) {
const response = await instance.acquireTokenPopup(request);
setAccessToken(response.accessToken);
}
}
if (accounts.length > 0) {
acquireToken();
}
}, [instance, accounts]);
if (!accessToken) return <div>Authenticating...</div>;
return (
<PowerBIEmbed
embedConfig={{
type: 'report',
id: 'report-id',
embedUrl: 'https://app.powerbi.com/reportEmbed?reportId=...',
accessToken: accessToken,
tokenType: models.TokenType.Aad, // AAD token
settings: {
panes: {
filters: { expanded: false },
pageNavigation: { visible: true }
}
}
}}
cssClassName="report-container"
/>
);
}
Backend Token Acquisition (C#)
public class PowerBIService
{
private readonly IConfidentialClientApplication _app;
public PowerBIService(IConfiguration config)
{
_app = ConfidentialClientApplicationBuilder
.Create(config["AzureAd:ClientId"])
.WithClientSecret(config["AzureAd:ClientSecret"])
.WithAuthority(new Uri($"https://login.microsoftonline.com/{config["AzureAd:TenantId"]}"))
.Build();
}
public async Task<string> GetUserToken(string userAssertion)
{
// On-behalf-of flow
var result = await _app.AcquireTokenOnBehalfOf(
new[] { "https://analysis.windows.net/powerbi/api/.default" },
new UserAssertion(userAssertion)
).ExecuteAsync();
return result.AccessToken;
}
}
SharePoint Integration
<!-- SharePoint Web Part -->
<script src="https://cdn.powerbi.com/libs/powerbi-client/2.19.1/powerbi.min.js"></script>
<div id="embedContainer"></div>
<script>
// Get SharePoint context token
async function getToken() {
const tokenResponse = await fetch('/_api/SP.OAuth.Token/Acquire', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
resource: 'https://analysis.windows.net/powerbi/api'
})
});
return (await tokenResponse.json()).access_token;
}
async function embedReport() {
const token = await getToken();
const config = {
type: 'report',
tokenType: powerbi.models.TokenType.Aad,
accessToken: token,
embedUrl: 'https://app.powerbi.com/reportEmbed?reportId=...',
id: 'report-id'
};
powerbi.embed(document.getElementById('embedContainer'), config);
}
embedReport();
</script>
Teams Tab Integration
import { app, authentication } from "@microsoft/teams-js";
import { PowerBIEmbed } from 'powerbi-client-react';
function TeamsTab() {
const [token, setToken] = useState(null);
useEffect(() => {
app.initialize().then(() => {
authentication.getAuthToken({
resources: ["https://analysis.windows.net/powerbi/api"]
}).then(setToken);
});
}, []);
if (!token) return <div>Loading...</div>;
return (
<PowerBIEmbed
embedConfig={{
type: 'report',
accessToken: token,
tokenType: 1, // AAD
embedUrl: embedUrl,
id: reportId
}}
/>
);
}
Permission Management
// Check user permissions before embedding
public async Task<bool> UserCanAccessReport(string userId, string reportId)
{
var client = await GetAuthenticatedClient(userId);
try
{
var report = await client.Reports.GetReportAsync(
Guid.Parse(_workspaceId),
Guid.Parse(reportId)
);
return true;
}
catch (HttpOperationException ex) when (ex.Response.StatusCode == HttpStatusCode.Forbidden)
{
return false;
}
}
Best Practices
authentication:
- Use MSAL for token acquisition
- Implement token caching
- Handle token refresh gracefully
permissions:
- Verify user access before embedding
- Respect Power BI sharing settings
- Use workspaces for permission management
user_experience:
- Match app theme with Power BI theme
- Handle authentication errors gracefully
- Provide fallback for unlicensed users
Conclusion
Embed for organization leverages existing Power BI investments:
- Seamless Azure AD integration
- Respects organizational security policies
- No additional capacity costs
- Full Power BI feature set
It’s ideal for internal applications requiring rich analytics.