Earn a 50% discount on the DP-600 certification exam by completing the Fabric 30 Days to Learn It challenge.
I am using embedded powerbi report in my react application. I am encountering a problem where in order to avoid the token expiry and sign in screen, I am fetching a new token 10 mins before the expiration time as per the following documentation:
But even after setting the new token, the page shows the sign-in screen. Can anyone suggest any solution to this?
Make sure the session refreshes and doesn't expire?
How to ensure the session is not expired in 10 mins of tab inactivity? I noticed if the tab is inactive for 10 mins, the session expires automatically and I have to click Refresh button.
Hi @nkshriva ,
Can you provide me with the code you are currently configuring to refresh the token periodically? If the login page is still popping up even after the AAD token is refreshed, could you try to add an action to refresh the report frontend page every half hour/ or 40 minutes? Make sure the session refreshes and doesn't expire?
Best Regards,
Liu Yang
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.
This is the code which I am using to use embeded powerbi report.
import { PowerBIEmbed } from 'powerbi-client-react';
import { useEffect, useState, useRef } from 'react';
import { useDispatch } from 'react-redux';
import { models } from 'powerbi-client';
import axios from 'services';
import { useLocation } from 'react-router-dom';
import { ButtonGroup, ButtonToolbar } from 'react-bootstrap';
import Button from 'Components/Button';
import TextField from 'Components/TextField';
import Spinner from 'Components/Spinner';
import {
setSecondaryHeader
} from 'store/slice/headerInfo';
const ReportOne = () => {
const [report, setReport] = useState(null);
const [config, setConfig] = useState({
type: 'report',
embedUrl: undefined,
accessToken: undefined
});
const expirationTokenRef = useRef({});
const reportRef = useRef({});
const [edit, setEdit] = useState(false);
const [name, setName] = useState('');
const location = useLocation();
const [isEmbedded, setIsEmbedded] = useState(false);
const [isLoading, setIsLoading] = useState(true);
// const [tokenExpiration, setTokenExpiration] = useState(null);
const dispatch = useDispatch();
useEffect(() => {
console.log(location);
setIsLoading(true);
if (!location) return;
dispatch(setSecondaryHeader({
path: 'Reports_View Reports',
route: '/reports/view_reports',
section: 'Reports',
subSection: 'View Reports'
}));
let postfix;
if (location.pathname.includes('paginated')) {
postfix = location.pathname.split('paginated/')[1];
} else {
// postfix = location.pathname.split('report/')[1];
postfix = location.pathname.split('nonpaginated/')[1];
}
// const postfix = location.pathname.split('report/')[1];
(async () => {
const res = await axios.get(`pbi/report_embed_config?report_id=${postfix}`);
console.log('expiration token', res.data?.expiration);
const newConfig = {
embedUrl: res.data?.report_details?.embed_url,
accessToken: res.data?.token
};
if (location.pathname.includes('paginated')) {
newConfig.uniqueId = res.data?.report_details?.report_id;
} else {
newConfig.id = res.data?.report_details?.report_id;
}
expirationTokenRef.current = res.data?.expiration;
setConfig(newConfig);
setIsEmbedded(true);
setIsLoading(false);
})();
}, [location]);
console.log(config);
const updateToken = async reportId => {
console.log('inside update token');
// Generate a new embed token or refresh the user Azure AD access token
const newAccessToken = await axios.get(`pbi/report_embed_config?report_id=${reportId}`);
// Update the new token expiration time
// setTokenExpiration(newAccessToken.data?.expiration);
expirationTokenRef.current = newAccessToken.data?.expiration;
// Set the new access token
await reportRef.current.setAccessToken(newAccessToken.data?.token);
};
const checkTokenAndUpdate = reportId => {
// Get the current time
const currentTime = Date.now();
const expiration = Date.parse(expirationTokenRef.current);
// Time until token expiration in milliseconds
const timeUntilExpiration = expiration - currentTime;
const timeToUpdate = 10 * 60 * 1000;
console.log(currentTime, expirationTokenRef.current, expiration, timeUntilExpiration, timeToUpdate);
// Update the token if it is about to expired
if (timeUntilExpiration <= timeToUpdate) {
console.log(currentTime, expiration, timeUntilExpiration, timeToUpdate);
let postfix;
if (location.pathname.includes('paginated')) {
postfix = location.pathname.split('paginated/')[1];
} else {
// postfix = location.pathname.split('report/')[1];
postfix = location.pathname.split('nonpaginated/')[1];
}
console.log('Updating report access token');
updateToken(postfix);
}
};
useEffect(() => {
if (!report) return;
if (edit) {
report.switchMode('edit');
} else {
report.switchMode('view');
}
}, [edit, report]);
useEffect(() => {
let postfix;
if (location.pathname.includes('paginated')) {
postfix = location.pathname.split('paginated/')[1];
} else {
// postfix = location.pathname.split('report/')[1];
postfix = location.pathname.split('nonpaginated/')[1];
}
document.addEventListener('visibilitychange', function () {
// Check the access token when the tab is visible
console.log('visibilitychange');
if (!document.hidden) {
checkTokenAndUpdate(postfix);
}
});
const tokenTimer = setInterval(() => {
checkTokenAndUpdate(postfix);
}, 60000);
return () => {
clearInterval(tokenTimer);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<>
{isLoading && <Spinner type='content' />}
{!isLoading &&
<div>
<ButtonToolbar
className='justify-content-between'
style={{ margin: 8 }}>
<ButtonGroup className='me-2'>
<Button
variant='primary'
style={{
display: 'none'
}}
onClick={() => setEdit(prev => !prev)}>
{edit ? 'View' : 'Edit'}
</Button>
</ButtonGroup>
{edit &&
<ButtonToolbar>
<ButtonGroup className='me-2'>
<Button
style={{ display: 'none' }}
variant='primary'
onClick={() => report.save()}>
Save
</Button>
</ButtonGroup>
<ButtonGroup className='me-2'>
<TextField
className='me-2'
value={name}
onChange={e => setName(e.target.value)} />
</ButtonGroup>
<ButtonGroup className='me-2'>
<Button
variant='primary'
disabled
onClick={() => {
report.saveAs({
name
});
setName('');
}}>
Save As
</Button>
</ButtonGroup>
</ButtonToolbar>}
</ButtonToolbar>
{isEmbedded ? <PowerBIEmbed
embedConfig={{
...config,
type: 'report', // Supported types: report, dashboard, tile, visual, qna, paginated report and create
tokenType: models.TokenType.Embed, // Use models.TokenType.Aad for SaaS embed
settings: {
panes: {
filters: {
expanded: false,
visible: false
}
},
background: models.BackgroundType.Transparent
},
permissions: models.Permissions.All
// viewMode: models.viewMode.Edit
}}
cssClassName='reportClass'
getEmbeddedComponent={embeddedReport => {
setReport(embeddedReport);
reportRef.current = embeddedReport;
}}
/> : null}
</div>}
</>
);
};
export default ReportOne;
User | Count |
---|---|
14 | |
4 | |
2 | |
1 | |
1 |
User | Count |
---|---|
21 | |
3 | |
2 | |
2 | |
2 |