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.
Hi Experts,
I have created a custom Power query connector for Procore with OAUTH2 authorization with autorization code as mentioned by procore developer team here ( following Microsoft's guide).
I am able to login and extract data but everytime I input a different URL as an source, the previous authentication becomes invalid and it again asks for authentication and keeps on asking whenever there is a new url.
I suspect my code is not able to refresh token and hence it keeps on asking for a new token. Can anyone guide me on how I can :
1. Make token refresh fuctionality to work in my code ? OR
2. Include all required tables\endpoints inside the connector code itself so that it will ingest all data in one go while connecting automatically.
Any help will be highly appreciated and I have spent ages over it.
Below is my code for your reference:
// This file contains your Data Connector logic
section ProcoreConnector;
// Procore OAuth2 values
client_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
client_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
redirect_uri = "https://oauth.powerbi.com/views/oauthredirect.html";
token_uri = "https://login.procore.com/oauth/token";
authorize_uri = "https://login.procore.com/oauth/authorize";
logout_uri = "https://login.microsoftonline.com/logout.srf";
// Login modal window dimensions
windowWidth = 720;
windowHeight = 1024;
// OAuth2 scope
scope_prefix = "";
scopes = {
""
};
[DataSource.Kind="ProcoreConnector", Publish="ProcoreConnector.Publish"]
shared ProcoreConnector.Contents = (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,
Logout=Logout
]
],
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",
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
// parse the full callbackUri, and extract the Query string
parts = Uri.Parts(callbackUri)[Query],
// if the query string contains an "error" field, raise an error
// otherwise call TokenMethod to exchange our code for an access_token
result = if (Record.HasFields(parts, {"error", "error_description"})) then
error Error.Record(parts[error], parts[error_description], parts)
else
TokenMethod("authorization_code", "code", parts[code])
in
result;
Refresh = (resourceUrl, refresh_token) => TokenMethod("refresh_token", "refresh_token", refresh_token);
Logout = (token) => logout_uri;
// 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") }
];
Solved! Go to Solution.
Hi @powerbi4ever,
I think this data connector works as excepted. (current power bi does not support global credentials for data source usage)
When you change the current URL, it means you are working with a different data source, so it will require you to input the new credentials.
For the folder or SharePoint connector, they have required credentials of the parent level permissions, then their connector can iterator and list their child contents at the same time.
Regards,
Xiaoxin Sheng
Hi @powerbi4ever,
I think this data connector works as excepted. (current power bi does not support global credentials for data source usage)
When you change the current URL, it means you are working with a different data source, so it will require you to input the new credentials.
For the folder or SharePoint connector, they have required credentials of the parent level permissions, then their connector can iterator and list their child contents at the same time.
Regards,
Xiaoxin Sheng
Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City
Check out the April 2024 Power BI update to learn about new features.
User | Count |
---|---|
13 | |
2 | |
1 | |
1 | |
1 |
User | Count |
---|---|
25 | |
3 | |
2 | |
2 | |
2 |