<?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: Custom Connector - Unreliable authentication in Developer</title>
    <link>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3752197#M50240</link>
    <description>&lt;LI-CODE lang="markup"&gt;The API Token generated from the data source is 'good' for one hour, so I don't think this is an issue of an expiring token.&lt;/LI-CODE&gt;
&lt;P&gt;not so sure about that.&amp;nbsp; Could be the culprit.&lt;/P&gt;</description>
    <pubDate>Fri, 08 Mar 2024 23:07:30 GMT</pubDate>
    <dc:creator>lbendlin</dc:creator>
    <dc:date>2024-03-08T23:07:30Z</dc:date>
    <item>
      <title>Custom Connector - Unreliable authentication</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3751909#M50229</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have a custom connector for Power BI that connects to a REST API to pull data. &amp;nbsp;The authentication path is OAuth, so when setting up the connecter you must enter the base URL for the datasource, a Client ID, and a Client Secret (there are optional variables to set query parameters).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The connector works perfectly when testing in Visual Studio Code, but when setting up in Power BI desktop the authentication only works sporadically. &amp;nbsp;Sometimes it works perfectly, sometimes it throws and authentication error when first setting up, sometimes it works fine when setting up but then later throws an authentication error when you try to refresh data:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Can't authenticate.png" style="width: 400px;"&gt;&lt;img src="https://community.fabric.microsoft.com/t5/image/serverpage/image-id/1056855iBB1182E282DBB2CA/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Can't authenticate.png" alt="Can't authenticate.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt; I've seen this same error posted in other threads, but can't find an actual answer to why it is happening.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Here is my connector code:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;// This file contains your Data Connector logic&lt;BR /&gt;[Version = "1.0.0"]&lt;BR /&gt;section Connect;&lt;/P&gt;&lt;P&gt;[DataSource.Kind = "Connect", Publish = "Connect.Publish"]&lt;BR /&gt;shared Connect.AbstractItems =&lt;BR /&gt;(&lt;BR /&gt;ConnectURL as text,&lt;BR /&gt;client_id as text, //OAuth Client ID&lt;BR /&gt;client_secret as text, //OAuth Client Secret&lt;BR /&gt;optional projectId as text,&lt;BR /&gt;optional itemType as text&lt;BR /&gt;) =&amp;gt;&lt;BR /&gt;let&lt;BR /&gt;//Get the access token and build header from OAuth clientID / clientSecret&lt;BR /&gt;token = FetchToken(ConnectURL, client_id, client_secret),&lt;BR /&gt;header = [#"Authorization" = "Bearer " &amp;amp; token],&lt;BR /&gt;&lt;BR /&gt;//Build query string and endpoint URL based on parameters&lt;BR /&gt;query = if (projectId &amp;lt;&amp;gt; null and itemType &amp;lt;&amp;gt; null) then "?project=" &amp;amp; projectId &amp;amp; "&amp;amp;itemType=" &amp;amp; itemType&lt;BR /&gt;else if (projectId &amp;lt;&amp;gt; null) then "?project=" &amp;amp; projectId&lt;BR /&gt;else if (itemType &amp;lt;&amp;gt; null) then "?itemType=" &amp;amp; itemType&lt;BR /&gt;else "",&lt;BR /&gt;abstractItemsUrl = ConnectURL &amp;amp; "/rest/latest/abstractitems",&lt;/P&gt;&lt;P&gt;//Method to get a single page of data from given url and start index position&lt;BR /&gt;GetPage = (abstractItemsUrl, start) =&amp;gt;&lt;BR /&gt;let&lt;BR /&gt;newQuery = if (query &amp;lt;&amp;gt; "" and query &amp;lt;&amp;gt; null) then query &amp;amp; "&amp;amp;startAt=" else "?startAt=",&lt;BR /&gt;newUrl = abstractItemsUrl &amp;amp; newQuery &amp;amp; start,&lt;BR /&gt;jsonResponse = Web.Contents(&lt;BR /&gt;newUrl,&lt;BR /&gt;[Headers = header]&lt;BR /&gt;),&lt;BR /&gt;doc = Json.Document(jsonResponse),&lt;BR /&gt;newData = doc[data],&lt;BR /&gt;newMeta = doc[#"meta"],&lt;BR /&gt;newTable = Table.FromRecords(&lt;BR /&gt;newData,&lt;BR /&gt;type table[&lt;BR /&gt;id = Number.Type,&lt;BR /&gt;itemType = Number.Type,&lt;BR /&gt;project = Number.Type,&lt;BR /&gt;createdDate = Text.Type,&lt;BR /&gt;modifiedDate = Text.Type,&lt;BR /&gt;lastActivityDate = Text.Type,&lt;BR /&gt;createdBy = Number.Type,&lt;BR /&gt;modifiedBy = Number.Type,&lt;BR /&gt;fields = Text.Type&lt;BR /&gt;]&lt;BR /&gt;),&lt;BR /&gt;startIndex = doc[Meta][pageInfo][startIndex],&lt;BR /&gt;totalResults = doc[Meta][pageInfo][totalResults],&lt;BR /&gt;response = [Meta = newMeta, Data = newTable]&lt;BR /&gt;in&lt;BR /&gt;response,&lt;/P&gt;&lt;P&gt;//Recursive call to GetPage method for paginated table of results&lt;BR /&gt;GeneratedList =&lt;BR /&gt;List.Generate(&lt;BR /&gt;() =&amp;gt;[i = 0, res = GetPage(abstractItemsUrl, Text.From(i))],&lt;BR /&gt;each [i] &amp;lt; [res][Meta][pageInfo][totalResults] and [res][Data] &amp;lt;&amp;gt; null,&lt;BR /&gt;each [i = [i] + 20, res = GetPage(abstractItemsUrl, Text.From(i))],&lt;BR /&gt;each [res][Data]),&lt;BR /&gt;ConvertedData = Table.FromList(GeneratedList, Splitter.SplitByNothing(), null, null, ExtraValues.Error),&lt;BR /&gt;ExpandedList = Table.ExpandListColumn(ConvertedData, "Column1"),&lt;BR /&gt;ExpandedRecords = try Table.ExpandRecordColumn(ExpandedList, "Column1",&lt;BR /&gt;{"id", "itemType", "project", "createdDate", "modifiedDate", "lastActivityDate", "createdBy", "modifiedBy", "fields"}) otherwise null&lt;BR /&gt;in&lt;BR /&gt;ExpandedRecords;&lt;/P&gt;&lt;P&gt;//Method to fetch access token from Connect&lt;BR /&gt;FetchToken = (ConnectURL as text, clientId as text, clientSecret as text) =&amp;gt;&lt;BR /&gt;let&lt;BR /&gt;url = Uri.Combine(ConnectURL, "/rest/oauth/token?grant_type=client_credentials"),&lt;BR /&gt;headers = [&lt;BR /&gt;#"Authorization" = "Basic " &amp;amp; Binary.ToText(Text.ToBinary(clientId &amp;amp; ":" &amp;amp; clientSecret), BinaryEncoding.Base64)&lt;BR /&gt;],&lt;BR /&gt;response = Web.Contents(&lt;BR /&gt;url,&lt;BR /&gt;[&lt;BR /&gt;Headers = headers,&lt;BR /&gt;Content = Text.ToBinary("")&lt;BR /&gt;]&lt;BR /&gt;),&lt;BR /&gt;jsonResponse = Json.Document(response),&lt;BR /&gt;accessToken = jsonResponse[access_token]&lt;BR /&gt;in&lt;BR /&gt;accessToken;&lt;/P&gt;&lt;P&gt;// Data Source Kind description&lt;BR /&gt;Connect = [&lt;BR /&gt;TestConnection = (dataSourcePath) =&amp;gt; {"Connect.AbstractItems", dataSourcePath},&lt;BR /&gt;Authentication = [&lt;BR /&gt;Anonymous = []&lt;BR /&gt;],&lt;BR /&gt;Label = "Authentication"&lt;BR /&gt;];&lt;/P&gt;&lt;P&gt;// Data Source UI publishing description&lt;BR /&gt;Connect.Publish = [&lt;BR /&gt;Beta = true,&lt;BR /&gt;Category = "Online Services",&lt;BR /&gt;ButtonText = { Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp") },&lt;BR /&gt;SourceImage = Connect.Icons,&lt;BR /&gt;SourceTypeImage = Connect.Icons&lt;BR /&gt;];&lt;/P&gt;&lt;P&gt;Connect.Icons = [&lt;BR /&gt;Icon16 = { Extension.Contents("Connect16.png"), Extension.Contents("Connect20.png"), Extension.Contents("Connect24.png"), Extension.Contents("Connect32.png") },&lt;BR /&gt;Icon32 = { Extension.Contents("Connect32.png"), Extension.Contents("Connect40.png"), Extension.Contents("Connect48.png"), Extension.Contents("Connect64.png") }&lt;BR /&gt;];&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;The connector code has the TestConnection, which was pointed out as missing in other threads, and it works when I test it in Visual Studio Code.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I can sometimes get around this error by generating a new client ID and client Secret for the same user account and retrying.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;A few other things:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;The user credentials have full admin access to the data source, so this is not a permission issue.&lt;/LI&gt;&lt;LI&gt;The connector uses the Client ID and Client Secret to request a Token from the data source and uses that token in the actual API query&lt;/LI&gt;&lt;LI&gt;The data source API limits the number of results to a maximum of 20 with each call, so the connector is set up to paginate results through looped calls until all data has been returned.&lt;/LI&gt;&lt;LI&gt;The API Token generated from the data source is 'good' for one hour, so I don't think this is an issue of an expiring token.&lt;/LI&gt;&lt;LI&gt;I use this connector multiple times within the same Power BI project to create different tables, and would like to be able to use the same Client ID and Client Secret each time I set up a new data source with this connector.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Can anyone help me figure out what the issue might be?&lt;/P&gt;</description>
      <pubDate>Fri, 08 Mar 2024 17:06:20 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3751909#M50229</guid>
      <dc:creator>pgarman</dc:creator>
      <dc:date>2024-03-08T17:06:20Z</dc:date>
    </item>
    <item>
      <title>Re: Custom Connector - Unreliable authentication</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3752197#M50240</link>
      <description>&lt;LI-CODE lang="markup"&gt;The API Token generated from the data source is 'good' for one hour, so I don't think this is an issue of an expiring token.&lt;/LI-CODE&gt;
&lt;P&gt;not so sure about that.&amp;nbsp; Could be the culprit.&lt;/P&gt;</description>
      <pubDate>Fri, 08 Mar 2024 23:07:30 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3752197#M50240</guid>
      <dc:creator>lbendlin</dc:creator>
      <dc:date>2024-03-08T23:07:30Z</dc:date>
    </item>
    <item>
      <title>Re: Custom Connector - Unreliable authentication</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3755649#M50315</link>
      <description>&lt;P&gt;&lt;a href="https://community.fabric.microsoft.com/t5/user/viewprofilepage/user-id/100342"&gt;@lbendlin&lt;/a&gt;&amp;nbsp;I know that the API token doesn't expire for an hour, and anytime the connector is 'refreshed' in Power BI a new token is generated.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Is there a way to get error logs out of Power BI desktop for something like this so I can see the exact error message returned by the data source?&lt;/P&gt;</description>
      <pubDate>Mon, 11 Mar 2024 15:07:18 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3755649#M50315</guid>
      <dc:creator>pgarman</dc:creator>
      <dc:date>2024-03-11T15:07:18Z</dc:date>
    </item>
    <item>
      <title>Re: Custom Connector - Unreliable authentication</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3755731#M50317</link>
      <description>&lt;P&gt;You should be able to see the issue when running network traces on that machine. Wireshark or the F12 tools etc.&lt;/P&gt;</description>
      <pubDate>Mon, 11 Mar 2024 15:46:13 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-Unreliable-authentication/m-p/3755731#M50317</guid>
      <dc:creator>lbendlin</dc:creator>
      <dc:date>2024-03-11T15:46:13Z</dc:date>
    </item>
  </channel>
</rss>

