Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
clongaw
Frequent Visitor

Unable to access all needed Credentials for Refresh in OAuth flow in Custom Connector

I have a Custom Connector with a working OAuth flow. I have a working TestConnection function and am able to freely pull data. While trying to create the Refresh function for the flow, I keep running into the following error when I try to access Extension.CurrentCredential() in the Refresh function. 

[9:42:48 AM]	[Info]	RefreshCredential result {
    "Details": "Object reference not set to an instance of an object.",
    "Message": "Exception received during credential refresh.",
    "Status": "Failure"
}

 

I need to have access to the expired AccessToken, the RefreshToken, and a special Code in the function for this particular OAuth flow. I have successfully saved all the information in Extension.CurrentCredentials(), but cannot seem to pass it to the Refresh function.

[9:48:58 AM]	[Info]	ListCredentials result [
    {
        "DataSource": {
            "Kind": "OAuthTest",
            "NormalizedPath": "path",
            "Path": "path"
        },
        "AuthenticationKind": "OAuth2",
        "Properties": {
            "AccessToken": "******",
            "Expires": null,
            "RefreshToken": "******",
            "hResult": "0",
            "code": "code"
        }
    }
]

 

Here is the beginning part of the Refresh function which is causing the error. 

Refresh = (dataSourcePath, refreshToken) => 
    let
        credentials = Extension.CurrentCredential()[Properties],
        oldAccessToken = credentials[AccessToken],
        oldRefreshToken = refreshToken,
        code = credentials[code],

 

I have also tried Extension.CurrentCredential()[access_token], but continue to get the 'Object reference...' error. 

 

1 ACCEPTED SOLUTION
clongaw
Frequent Visitor

I have found a solution for my approach and have also seen another option that may be viable. The solution I am using is to set the RefreshToken in credentials as the value "access_token;refresh_token;access_code" as these are the three variables that I need. I do this by taking the TokenResult from Web.Contents and renaming or setting the Record Fields corresponding to access_token and RefreshToken:

JsonResponse = Json.Document(TokenResult),
JsonRenamed = Record.RenameFields(JsonResponse, {{"token","access_token"}, {"refreshToken", "RefreshToken"}}) & 
            [RefreshToken = JsonResponse[token] & ";" & JsonResponse[refreshToken] & ";" & code, Expires = 900]
    in
        JsonRenamed;

I can then call Refresh as 

Refresh = (dataSourcePath, tokens) => 
    let
        TokenList = Text.Split(tokens, ";"),
        accessToken = TokenList{0},
        refreshToken = TokenList{1},
        code = TokenList{2},
   ...
   in  
       output

 

The second option I have seen uses oldCredential to store and access all the old information. This is most likely cleaner, but I have not verified if it works with adding a custom field to the Credentials record to store the special access_code I need. You can see more examples of this technique here: https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-failing-on-refreshing-data-with...

View solution in original post

1 REPLY 1
clongaw
Frequent Visitor

I have found a solution for my approach and have also seen another option that may be viable. The solution I am using is to set the RefreshToken in credentials as the value "access_token;refresh_token;access_code" as these are the three variables that I need. I do this by taking the TokenResult from Web.Contents and renaming or setting the Record Fields corresponding to access_token and RefreshToken:

JsonResponse = Json.Document(TokenResult),
JsonRenamed = Record.RenameFields(JsonResponse, {{"token","access_token"}, {"refreshToken", "RefreshToken"}}) & 
            [RefreshToken = JsonResponse[token] & ";" & JsonResponse[refreshToken] & ";" & code, Expires = 900]
    in
        JsonRenamed;

I can then call Refresh as 

Refresh = (dataSourcePath, tokens) => 
    let
        TokenList = Text.Split(tokens, ";"),
        accessToken = TokenList{0},
        refreshToken = TokenList{1},
        code = TokenList{2},
   ...
   in  
       output

 

The second option I have seen uses oldCredential to store and access all the old information. This is most likely cleaner, but I have not verified if it works with adding a custom field to the Credentials record to store the special access_code I need. You can see more examples of this technique here: https://community.fabric.microsoft.com/t5/Developer/Custom-Connector-failing-on-refreshing-data-with...

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.