Hello,
I have a custom connector which uses OAuth2 with my Django web app.
It works correctly with Power BI desktop and in the Visual Studio Code Power Query SDK.
I have set up an On-Premises Data Gateway to use it in the Power BI service, but I cannot get it to work.
In the Power BI service, when I choose "Edit credentials", either when creating a new connection to my gateway, or manually adding the datasource of my semantic model to my gateway:
If I manually close the popup the connect button is greyed out.
I have tried changing my pbi_redirect_uri to https://gatewayadminportal.azure.com/OAuthRedirect, but then it never makes a request to my web app. The popup opens and closes, and then when I try to create the connection it makes a post request to my web app with no auth token.
Can anyone tell me where https://gatewayadminportal.azure.com/OAuthRedirect is coming from, and ideally how to make my connector work in the Power BI service?
Thank you
Additional info:
I do not have a Power BI premium license or premium workspace.
I am not using the (personal) gateway.
powerQRy.pq:
[Version = "1.0.0"]
section powerQRy;
//==== OAuth2 with PBI requires PKCE - https://learn.microsoft.com/en-us/power-query/handling-authentication ====
Base64UrlEncodeWithoutPadding = (hash as binary) as text =>
let
base64Encoded = Binary.ToText(hash, BinaryEncoding.Base64),
base64UrlEncoded = Text.Replace(Text.Replace(base64Encoded, "+", "-"), "/", "_"),
withoutPadding = Text.TrimEnd(base64UrlEncoded, "=")
in
withoutPadding;
code_verifier = Text.NewGuid() & Text.NewGuid();
code_challenge = Base64UrlEncodeWithoutPadding(Crypto.CreateHash(CryptoAlgorithm.SHA256, Text.ToBinary(code_verifier, TextEncoding.Ascii)));
// ==== ====
oauth_client_id = "***";
base_url = "https://***/";
authorization_url = base_url & "oauth/authorize/";
token_url = base_url & "oauth/token/";
content_url = base_url & "api/power_bi/tables";
pbi_redirect_uri = "https://oauth.powerbi.com/views/oauthredirect.html";
[DataSource.Kind="powerQRy", Publish="powerQRy.Publish"]
shared powerQRy.Contents = () =>
let
headers =
[
#"Authorization" = "Bearer " & Extension.CurrentCredential()[access_token],
#"Content-Type" = "application/json"
],
response = Json.Document(Web.Contents(content_url, [Headers = headers])),
responseTable = Table.FromRecords(response, {"app", "name", "route_endpoint", "isLeaf"})
in
responseTable;
powerQRy = [
TestConnection = (dataSourcePath) => { "powerQRy.Contents" },
Authentication = [
OAuth = [
StartLogin = StartLogin,
FinishLogin = FinishLogin
]
],
Label = "powerQRy"
];
StartLogin = (resourceUrl, state, display) =>
let
AuthorizeUrl = authorization_url & "?" &
Uri.BuildQueryString([
client_id = oauth_client_id,
response_type = "code",
redirect_uri = pbi_redirect_uri,
state = state,
scope = "read",
code_challenge = code_challenge,
code_challenge_method = "S256"
])
in
[
LoginUri = AuthorizeUrl,
CallbackUri = pbi_redirect_uri,
WindowHeight = 780,
WindowWidth = 1024,
Context = [
code_verifier = code_verifier
]
];
FinishLogin = (context, callbackUri, state) =>
let
Parts = Uri.Parts(callbackUri),
Code = Record.FieldOrDefault(Parts[Query], "code", ""),
TokenResponse = Json.Document(Web.Contents(
token_url,
[
Content = Text.ToBinary(Uri.BuildQueryString([
grant_type = "authorization_code",
code = Code,
redirect_uri = pbi_redirect_uri,
client_id = oauth_client_id,
code_verifier = context[code_verifier]
])),
Headers = [#"Content-Type" = "application/x-www-form-urlencoded"]
]
))
in
TokenResponse;
powerQRy.Publish = [
Beta = true,
Category = "Other",
ButtonText = { Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp") },
LearnMoreUrl = "https://powerbi.microsoft.com/",
SourceImage = powerQRy.Icons,
SourceTypeImage = powerQRy.Icons
];
powerQRy.Icons = [
Icon16 = {
Extension.Contents("powerQRy16.png"),
Extension.Contents("powerQRy20.png"),
Extension.Contents("powerQRy24.png"),
Extension.Contents("powerQRy32.png")
},
Icon32 = {
Extension.Contents("powerQRy32.png"),
Extension.Contents("powerQRy40.png"),
Extension.Contents("powerQRy48.png"),
Extension.Contents("powerQRy64.png")
}
];