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

Enhance your career with this limited time 50% discount on Fabric and Power BI exams. Ends August 31st. Request your voucher.

Reply
SMax
New Member

Power Query Custom Connector Issue

Hi Experts,

@mattmasson  @colinpop @zhouguyin @GuyInACube 

I am trying to build a custom connector for using the below code but I am facing the below difficulties ( I am assuming that after getting the auth code the process is not able to move forward) :

1. While testing the code successfully generates the authorization code but nothing happens after that.

2. Ideally the process should automatically get the access token after receiving the code and finish login which is not happening. Any pointers will be much appreciated. Below is the code :

 

 

 

 

// This file contains your Data Connector logic
section ProcoreConnector;

// Procore OAuth2 values
client_id = Text.FromBinary(Extension.Contents("client_id.txt"));
client_secret = Text.FromBinary(Extension.Contents("client_secret.txt"));
redirect_uri = "urn:ietf:wg:oauth:2.0:oob";
token_uri = "https://login.procore.com/oauth/token";
authorize_uri = "https://login.procore.com/oauth/authorize";

// Login modal window dimensions
windowWidth = 720;
windowHeight = 1024;

// OAuth2 scope
scope_prefix = "";
scopes = {
    ""
};


[DataSource.Kind="ProcoreConnector", Publish="ProcoreConnector.Publish"]
shared ProcoreConnector.Contents = (optional url as text) =>
    let
        source = Json.Document(Web.Contents(url))
    in
        source; 

// Data Source Kind description
ProcoreConnector= [
    TestConnection = (dataSourcePath) => { "ProcoreConnector.Contents", dataSourcePath },
    Authentication = [
        OAuth = [
            StartLogin=StartLogin,
            FinishLogin=FinishLogin,
            Refresh=Refresh
        ]
    ],
    Label = Extension.LoadString("DataSourceLabel")
];

// Data Source UI publishing description
ProcoreConnector.Publish = [
    Beta = true,
    Category = "Other",
    ButtonText = { Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp") },
    LearnMoreUrl = "https://developers.procore.com/",
    SourceImage = ProcoreConnector.Icons,
    SourceTypeImage = ProcoreConnector.Icons
];

// Helper functions for OAuth2: StartLogin, FinishLogin, Refresh, Logout
StartLogin = (resourceUrl, state, display) =>
    let
        authorizeUrl = authorize_uri & "?" & Uri.BuildQueryString([
            response_type = "code",
            scope = "",
            state = state,
            client_id = client_id,  
            redirect_uri = redirect_uri
        ])
    in
        [
            LoginUri = authorizeUrl,
            CallbackUri = redirect_uri,
            WindowHeight = 720,
            WindowWidth = 1024,
            Context = null
        ];

FinishLogin = (context, callbackUri, state) =>
    let
        Parts = Uri.Parts(callbackUri)[Query]
    in
        TokenMethod(Parts[code]);

Refresh = (resourceUrl, refresh_token) => TokenMethod("refresh_token", "refresh_token", refresh_token);

// see "Exchange code for access token: https://developers.procore.com/documentation/oauth-installed-apps for details
TokenMethod = (grantType, tokenField, code) =>
    let
        queryString = [
            grant_type = "authorization_code",
            redirect_uri = redirect_uri,
            client_id = client_id,
            client_secret = client_secret
        ],
        queryWithCode = Record.AddField(queryString, tokenField, code),

        tokenResponse = Web.Contents(token_uri, [
            Content = Text.ToBinary(Uri.BuildQueryString(queryWithCode)),
            Headers = [
                #"Content-type" = "application/x-www-form-urlencoded",
                #"Accept" = "application/json"
            ],
            ManualStatusHandling = {400} 
        ]),
        body = Json.Document(tokenResponse),
        result = if (Record.HasFields(body, {"error", "error_description"})) then 
                    error Error.Record(body[error], body[error_description], body)
                 else
                    body
    in
        result;
       

ProcoreConnector.Icons = [
    Icon16 = { Extension.Contents("ProcoreConnector16.png"), Extension.Contents("ProcoreConnector20.png"), Extension.Contents("ProcoreConnector24.png"), Extension.Contents("ProcoreConnector32.png") },
    Icon32 = { Extension.Contents("ProcoreConnector32.png"), Extension.Contents("ProcoreConnector40.png"), Extension.Contents("ProcoreConnector48.png"), Extension.Contents("ProcoreConnector64.png") }
];

 

 

 

 

 

2 REPLIES 2
Anonymous
Not applicable

The following code works. It might be worth comparing the two: https://community.fabric.microsoft.com/t5/Desktop/Custom-Zendesk-Connector-Power-Query-Code/td-p/240....  It's going to be difficult to find an answer to this without us being able to test it against the source. 

Anonymous
Not applicable

Hi @SMax 

What data source do you want to connect with in Power BI?

I think your code is used to get access token from your data source. Will it return error or other?

Here is a bolg with similar requirement like yours, I hope it could help you.

For reference: Power Query Open ID and OAuth 2.0 Rest API

REST API Get Access Token

 

Best Regards,
Rico Zhou

 

If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Helpful resources

Announcements
July 2025 community update carousel

Fabric Community Update - July 2025

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

July PBI25 Carousel

Power BI Monthly Update - July 2025

Check out the July 2025 Power BI update to learn about new features.