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

July 7 - July 17 | Round 2 of the Power BI Dataviz World Championships. Don't miss your chance! Learn more

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
FabCon and SQLCon Barcelona 2026

FabCon & SQLCon – Barcelona 2026

Join us in Barcelona for FabCon and SQLCon, the Fabric, Power BI, SQL, and AI community event. Save €200 with code FABCMTY200.

60 days of Data Days Carousel

Data Days 2026

Join Data Days 2026: 60 days of free live/on-demand sessions, challenges, study groups, and certification opportunities.

Power BI DataViz World Championships carousel

Power BI DataViz World Championships - June 2026

A new Power BI DataViz World Championship is coming this June! Don't miss out on submitting your entry.