<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: 'Generate Token' API returns token with variable (short) expirations: Using Service Principal in Developer</title>
    <link>https://community.fabric.microsoft.com/t5/Developer/Generate-Token-API-returns-token-with-variable-short-expirations/m-p/1215585#M24685</link>
    <description>&lt;P&gt;Yes, indeed&amp;nbsp;@Anonymous&lt;/a&gt;,&amp;nbsp; we are facing the exact same behaviour. The expiration of the token remains the same upon each new token-request, which doesn't seem to be normal.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;However, It looks like (approx.) 5 minutes before the expiration a new token can be requested which will give a new expiration time. We were able to handle this with a timer (within our SPA) that ends 5 minutes before the tokens' expiration, after which it will fetch a new token with a fresh expirationtime.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Fri, 10 Jul 2020 20:00:35 GMT</pubDate>
    <dc:creator>basvanleeuwen</dc:creator>
    <dc:date>2020-07-10T20:00:35Z</dc:date>
    <item>
      <title>'Generate Token' API returns token with variable (short) expirations: Using Service Principal</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Generate-Token-API-returns-token-with-variable-short-expirations/m-p/1042168#M23271</link>
      <description>&lt;P&gt;Hi All.&lt;BR /&gt;&lt;BR /&gt;I am migrating an application over to using Service Principal accounts with the Power BI REST API.&lt;BR /&gt;This works great - but then I noticed that embedded reports would sometimes stop working very quickly - with 401 (unauthorized) errors recorded in the browser dev-tools/console.&lt;BR /&gt;&lt;BR /&gt;I am using the 'Generate Token' API endpoint as described here: &lt;A title="Power BI API: Generate Token" href="https://docs.microsoft.com/en-us/rest/api/power-bi/embedtoken/generatetoken" target="_blank" rel="noopener"&gt;https://docs.microsoft.com/en-us/rest/api/power-bi/embedtoken/generatetoken&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;This is accessed by using an Azure access token generated via the &lt;SPAN class="break-text"&gt;&lt;A title="Microsoft.IdentityModel.Clients.ActiveDirectory" href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.clients.activedirectory?view=azure-dotnet" target="_blank" rel="noopener"&gt;Microsoft.IdentityModel.Clients.ActiveDirectory&lt;/A&gt;&lt;/SPAN&gt; library, which follows the Service Principal authentication flow in .Net Core.&lt;BR /&gt;&lt;BR /&gt;&lt;STRONG&gt;So what's the problem?&lt;/STRONG&gt;&lt;BR /&gt;The Azure AD Access token gets cached by the Identity Model Client - saving excessive calls to Azure (a good thing), however, when calling the Power BI REST API with this token - the resulting &lt;U&gt;Embedding&lt;/U&gt; token gets an expiration that matches the original AD access token.&lt;BR /&gt;&lt;BR /&gt;These AD tokens last an hour - and will get cached for that duration.&lt;BR /&gt;This means that at any time (depending on when your AD tokens are cached), you can end up with an embedding token that is only usable for a few seconds!&lt;BR /&gt;&lt;BR /&gt;&lt;STRONG&gt;Expected behaviour:&lt;/STRONG&gt;&lt;BR /&gt;Even if an AD token only has a couple of minutes before it expires - the Power BI API should issue embedding tokens with an expiration of a full hour.&lt;BR /&gt;&lt;BR /&gt;Is anyone else seeing this behaviour?&lt;BR /&gt;Does this need to be escalated as a support call?&lt;BR /&gt;&lt;BR /&gt;Thanks,&lt;BR /&gt;Matt&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 22 Apr 2020 16:20:23 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Generate-Token-API-returns-token-with-variable-short-expirations/m-p/1042168#M23271</guid>
      <dc:creator>Anonymous</dc:creator>
      <dc:date>2020-04-22T16:20:23Z</dc:date>
    </item>
    <item>
      <title>Re: 'Generate Token' API returns token with variable (short) expirations: Using Service Principal</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Generate-Token-API-returns-token-with-variable-short-expirations/m-p/1215585#M24685</link>
      <description>&lt;P&gt;Yes, indeed&amp;nbsp;@Anonymous&lt;/a&gt;,&amp;nbsp; we are facing the exact same behaviour. The expiration of the token remains the same upon each new token-request, which doesn't seem to be normal.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;However, It looks like (approx.) 5 minutes before the expiration a new token can be requested which will give a new expiration time. We were able to handle this with a timer (within our SPA) that ends 5 minutes before the tokens' expiration, after which it will fetch a new token with a fresh expirationtime.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 10 Jul 2020 20:00:35 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Generate-Token-API-returns-token-with-variable-short-expirations/m-p/1215585#M24685</guid>
      <dc:creator>basvanleeuwen</dc:creator>
      <dc:date>2020-07-10T20:00:35Z</dc:date>
    </item>
    <item>
      <title>Re: 'Generate Token' API returns token with variable (short) expirations: Using Service Principal</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Generate-Token-API-returns-token-with-variable-short-expirations/m-p/1231522#M24805</link>
      <description>&lt;P&gt;Hi &lt;a href="https://community.fabric.microsoft.com/t5/user/viewprofilepage/user-id/245172"&gt;@basvanleeuwen&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;I ended up taking a different route in the end, adding details here for others...&lt;BR /&gt;&lt;BR /&gt;The C# flow for creating an Authentication Context and passing in details for the Service Principal, results in the Azure auth token being cached within your application/api. After the first request, this cached token is then used for approximately 55 minutes (as you had noticed) - but you can manipulate this cache in code.&lt;BR /&gt;&lt;BR /&gt;C# even lets you handle the serialization of these tokens in cases where you don't want to use the built-in cache.&lt;BR /&gt;&lt;A title="GitHub - Azure ADAL Library for dotnet - Token Cache Serialization" href="https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/wiki/Token-cache-serialization" target="_blank" rel="noopener"&gt;https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/wiki/Token-cache-serialization&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;I didn't go the full custom serialization route, instead I opted for a simple cache invalidation method.&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;private async Task&amp;lt;AuthenticationResult&amp;gt; CallAuthTokenEndpoint()
{
    var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/...");
    var credential = new ClientCredential("abcd-1234-your-auth-client-id", "your-client-secret");

    ClearExpiredTokenCache(authenticationContext);

    return await authenticationContext.AcquireTokenAsync("https://analysis.windows.net/powerbi/api", credential);
}

private void ClearExpiredTokenCache(AuthenticationContext authenticationContext)
{
    var cachedItems = authenticationContext.TokenCache.ReadItems();
    var matchedItem = cachedItems.FirstOrDefault(tokenCacheItem =&amp;gt;
        string.Compare(tokenCacheItem.ClientId, "abcd-1234-your-auth-client-id",
            StringComparison.OrdinalIgnoreCase) == 0
        &amp;amp;&amp;amp; string.Compare(tokenCacheItem.Resource, "https://analysis.windows.net/powerbi/api",
            StringComparison.OrdinalIgnoreCase) == 0);

    if (matchedItem != null)
    {
        var expireIfAfter =
            DateTime.UtcNow.AddMinutes(50);

        if (expireIfAfter &amp;gt; matchedItem.ExpiresOn)
        {
            authenticationContext.TokenCache.DeleteItem(matchedItem);
        }
    }
}&lt;/LI-CODE&gt;&lt;P&gt;&lt;STRONG&gt;CallAuthTokenEndpoint&lt;/STRONG&gt; =&amp;gt; Is responsible for getting the Azure Auth Token, which will then be used by the Power BI API.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;The call to &lt;STRONG&gt;AquireTokenAsync&lt;/STRONG&gt; in this method, will return from the local cache (if a token has been generated within the last 55 minutes). So before calling this method, we can do our own clearing of the token cache - via the Authentication Context.&lt;BR /&gt;&lt;BR /&gt;&lt;STRONG&gt;ClearExpiredTokenCache&lt;/STRONG&gt; =&amp;gt; fetches all items from the local cache. Then finds the one that matches our ClientId and desired resource (analysis.windows.net/powerbi/api).&lt;BR /&gt;&lt;BR /&gt;If we find a matching token... then we can choose to clear it from the cache IF more than 10 minutes have passed. (Utc.Now + 50 mins).&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;With no token in the cache, the call to &lt;STRONG&gt;AquireTokenAsync&lt;/STRONG&gt; will always generate a new token with another 60 minutes on the clock.&lt;BR /&gt;&lt;BR /&gt;This obviously results in increased frequency of calls to Azure for auth tokens... but it gives you more flexibility for manging token durations.&lt;BR /&gt;&lt;BR /&gt;I am assuming that the Power BI token expiration being in-sync with the expiration of the Azure AD token, is by design.&lt;BR /&gt;Hopefully one of our suggestions will help other people in similar situations,&lt;BR /&gt;&lt;BR /&gt;Cheers, Matt&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 17 Jul 2020 16:01:21 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Generate-Token-API-returns-token-with-variable-short-expirations/m-p/1231522#M24805</guid>
      <dc:creator>Anonymous</dc:creator>
      <dc:date>2020-07-17T16:01:21Z</dc:date>
    </item>
  </channel>
</rss>

