Forum Discussion

PowerBIUserHoop's avatar
PowerBIUserHoop
Frequent Visitor
1 year ago
Solved

Refreshing the Report Token

Hi,

 

I am new to developing in PowerBI, I am looking at creating a dashbosrd from a PowerBI report using ASP.Net Core.

 

I have the report running fine, but am struggling with how to refresh the Token before it expires and generates the error messages:

 

ClientError_TokenExpired

 

We had trouble loading the settings for automatic page refresh, so this page won't refresh automatically. Try again in a few minutes.

 

I have tried several things but no success as yet.

 

Any advice greatly appriciated.

  • FarhanJeelani's avatar
    FarhanJeelani
    1 year ago

    To refresh the embed token in Power BI without reloading the page, you can replace the current token by calling the `setAccessToken` method on the report object in the Web UI. This method will apply the new token without requiring a page reload, keeping the session alive.

     

    Here's how you could modify your `getToken` method to use `setAccessToken`:

    1. Modify the `getToken` function: Update it to call `report.setAccessToken(newToken)` when a new token is fetched.

     

    2. Implement `setAccessToken`: After parsing the new token from the response, apply it directly to the existing report instance.

    Here's how your modified code could look:

    javascript

    function getToken() {
    $.ajax({
    type: "GET",
    url: "/embedinfo/getembedinfo",
    success: function (data) {
    var JSONdata = JSON.parse(data);
    var newToken = JSONdata.EmbedToken.Token;
    var Expiration = JSONdata.EmbedToken.Expiration;
    
    // Update the existing report with the new token
    if (report) {
    report.setAccessToken(newToken)
    .then(() => {
    console.log('Token refreshed successfully');
    })
    .catch(error => {
    console.error('Error setting new token:', error);
    });
    }
    
    console.log('New Token Expiration:', Expiration);
    },
    error: function (err) {
    console.error('Error fetching token:', err);
    }
    });
    }
    
    // Refresh token every 15 minutes or as required
    setInterval(getToken, 900000); // 15 minutes

     

    This approach will ensure that the new token is seamlessly applied to the report without needing to reload the page, maintaining the user's session with minimal interruption. Adjust the interval to refresh the token before the expiration time.

5 Replies

  • Anonymous's avatar
    Anonymous
    Not applicable

    Hi  PowerBIUserHoop ,

     

    As far as I know, access tokens generally expire in 60 minutes or less, and you'll need an access token policy and an update to it.

    Refresh tokens in the Microsoft identity platform - Microsoft identity platform | Microsoft Learn

     

    This is the related document, you can view this content:

    oauth - Handling Expired Refresh Tokens in ASP.NET Core - Stack Overflow

    Solved: Get data from API with token that expires - Microsoft Fabric Community

    Solved: Token expiring in Power BI embedded (error 403) - Microsoft Fabric Community

     

    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.

  • To automatically refresh the token in an ASP.NET Core application for a Power BI report, you can implement an approach that fetches a new access token before the current one expires. Here are some steps you can follow:

     

     1. Implement a Token Refresh Method
    Set up a method to retrieve a new token from Azure Active Directory (AAD) when the existing token expires. This usually involves setting up a method to request a new token using the client credentials or authorization flow.

    csharp

    public async Task<string> GetAccessToken()
    {
    var app = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithClientSecret(clientSecret)
    .WithAuthority(new Uri(authority))
    .Build();
    
    var scopes = new string[] { "https://analysis.windows.net/powerbi/api/.default" };
    AuthenticationResult result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
    return result.AccessToken;
    }

     

    2. Use a Timer or Background Service
    Set up a background task or timer in ASP.NET Core to refresh the token at regular intervals. A timer could be set to request a new token just before the old token expires. Alternatively, ASP.NET Core’s `IHostedService` can be used to handle token refresh in the background.

    For example:

    csharp

    public class TokenRefreshService : IHostedService, IDisposable
    {
    private Timer _timer;
    private readonly TokenProvider _tokenProvider; // Your service to get tokens
    
    public TokenRefreshService(TokenProvider tokenProvider)
    {
    _tokenProvider = tokenProvider;
    }
    
    public Task StartAsync(CancellationToken cancellationToken)
    {
    _timer = new Timer(RefreshToken, null, TimeSpan.Zero, TimeSpan.FromMinutes(50)); // Set before expiration
    return Task.CompletedTask;
    }
    
    private async void RefreshToken(object state)
    {
    await _tokenProvider.RefreshToken(); // Method to refresh and store token
    }
    
    public Task StopAsync(CancellationToken cancellationToken)
    {
    _timer?.Change(Timeout.Infinite, 0);
    return Task.CompletedTask;
    }
    
    public void Dispose()
    {
    _timer?.Dispose();
    }
    }



    3. Configure Token Refresh in the Frontend (JavaScript/HTML)
    In your frontend code, handle token expiration errors by requesting a new token. For instance, if you receive the `ClientError_TokenExpired` error, refresh the token and re-initialize the Power BI embedded report.

    javascript

    function refreshReport() {
    powerbi.get(reportContainer).embedConfig.accessToken = '<new_token>'; // Assign refreshed token
    powerbi.get(reportContainer).refresh(); // Reload the report
    }


     4. Store the Token Securely and Update It
    When you obtain a new token, store it securely (for example, in-memory cache) and ensure all subsequent requests use the latest token. Update your embed configurations or any other services that use this token.

     

    Additional Tips
    - Token Lifetime: Check your access token's lifetime and adjust the refresh frequency accordingly. For example, if the token lasts 60 minutes, you might refresh every 50 minutes.
    - Use Azure AD Library: Use the Microsoft Authentication Library (MSAL) to manage tokens if possible; it includes built-in token caching and refresh handling.

    Let me know if you need more details on any specific part!

    • PowerBIUserHoop's avatar
      PowerBIUserHoop
      Frequent Visitor

      Hi,

      Thanks for the reply.

       

      I have looked through the example peoject code and found a method:

       function getToken() {
           var dataret = '';
           $.ajax({
               type: "GET",
               url: "/embedinfo/getembedinfo",
               success: function (data) {
                   dataret = data;
                   var JSONdata = JSON.parse(data);
                   console.log(JSONdata);
                   var EmbedToken = JSONdata.EmbedToken;
                   var Expiration = EmbedToken.Expiration;
                   console.log('getToken - Expiration');
                   console.log(Expiration);
                   console.log('getToken - Expiration end');
                   console.log('getToken - report');
                   console.log(report);
                   lastLoadRequest = report.lastLoadRequest
                   console.log('getToken - report end');
                   console.log('getLastLoadDateTime - report start');
                   getLastLoadDateTime();
                   console.log('getLastLoadDateTime - report end');
                    
               },
               error: function (err) {
      
                   console.log(dataret)
               }
           });
       }
      setInterval(getToken, 15000);

       

      public string GetEmbedInfo()
      {
          try
          {
              // Validate whether all the required configurations are provided in appsettings.json
              string configValidationResult = ConfigValidatorService.ValidateConfig(azureAd, powerBI);
              if (configValidationResult != null)
              {
                  HttpContext.Response.StatusCode = 400;
                  return configValidationResult;
              }
      
              EmbedParams embedParams = pbiEmbedService.GetEmbedParams(new Guid(powerBI.Value.WorkspaceId), new Guid(powerBI.Value.ReportId));
              return JsonSerializer.Serialize<EmbedParams>(embedParams);
          }
          catch (Exception ex)
          {
              HttpContext.Response.StatusCode = 500;
              return ex.Message + "\n\n" + ex.StackTrace;
          }
      }

      This shows the token expiry in the console as increasing, but this doesn't work because if I wait until the original expiry date/time the report expires.

       

      Is there a method of applying the new token to the existing report in the Web UI rather than reloading the page?

       

       

       

       

       

       

      • FarhanJeelani's avatar
        FarhanJeelani
        Super User

        To refresh the embed token in Power BI without reloading the page, you can replace the current token by calling the `setAccessToken` method on the report object in the Web UI. This method will apply the new token without requiring a page reload, keeping the session alive.

         

        Here's how you could modify your `getToken` method to use `setAccessToken`:

        1. Modify the `getToken` function: Update it to call `report.setAccessToken(newToken)` when a new token is fetched.

         

        2. Implement `setAccessToken`: After parsing the new token from the response, apply it directly to the existing report instance.

        Here's how your modified code could look:

        javascript

        function getToken() {
        $.ajax({
        type: "GET",
        url: "/embedinfo/getembedinfo",
        success: function (data) {
        var JSONdata = JSON.parse(data);
        var newToken = JSONdata.EmbedToken.Token;
        var Expiration = JSONdata.EmbedToken.Expiration;
        
        // Update the existing report with the new token
        if (report) {
        report.setAccessToken(newToken)
        .then(() => {
        console.log('Token refreshed successfully');
        })
        .catch(error => {
        console.error('Error setting new token:', error);
        });
        }
        
        console.log('New Token Expiration:', Expiration);
        },
        error: function (err) {
        console.error('Error fetching token:', err);
        }
        });
        }
        
        // Refresh token every 15 minutes or as required
        setInterval(getToken, 900000); // 15 minutes

         

        This approach will ensure that the new token is seamlessly applied to the report without needing to reload the page, maintaining the user's session with minimal interruption. Adjust the interval to refresh the token before the expiration time.