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

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now! Learn more

Reply
Anonymous
Not applicable

Custom Data Connector issue with authentication

Hi

 

I've created a custom data connector using Oauth flow. I'm receiving an error once I select my account to login. Error description below:

 

"[Invalid Grant] AADB2C90090: The provided JWE is not a valid 5 segment token."

 

I've tried searching in google and found a few posts but no concrete solution.

 

Can someone familiar advise what's wrong here and how can I solve it?

 

Thanks
AfsarP1

4 REPLIES 4
v-juanli-msft
Community Support
Community Support

Hi @Anonymous 

What data source do you connect to?

How do you define the oauth flow in the custom connector?

Here is an example:

https://jussiroine.com/2019/02/building-a-custom-connector-for-power-bi-that-supports-oauth2-to-visualize-my-wellness-data/

 

Best Regards

Maggie

Anonymous
Not applicable

Hi Maggie
 
Looks like my response was marked as SPAM. Resending:
 
I'm building a connector that connects to our cloud environment. I've looked at Jussi's blog and also codes from Matt Mason(MyGraphmost) on Gihub to build below code:
 

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

 

client_id = Text.FromBinary(Extension.Contents("client_id.txt"));
redirect_uri = "https://ourdomain/oauth2/authresp";
token_uri = "https://ourdomain/oauth2/v2.0/token"; //Used to retrieve an access token
authorize_uri = "https://ourdomain/oauth2/authorize";
logout_uri = "https://login.microsoftonline.com/logout.srf";

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

// OAuth2 scope
scope_prefix = "https://ourdomian.com";
scopes = {
"daily",
"User.Read",
"openid"
//".Read.All",
//"IdentityProvider.Read.All"
//"client_id"

//It can be delegated permission or app permission https://docs.microsoft.com/en-us/graph/auth/auth-concepts#microsoft-graph-permissions
};

[DataSource.Kind="System", Publish="System.Publish"]
shared System.Contents = (url as text) =>

let
source = Json.Document(Web.Contents(url)) //If the data is returned from the datasource in JSON format

in
source;

// Data Source Kind description
System = [
TestConnection = (dataSourcePath) => { "System.Contents", dataSourcePath },
Authentication = [
OAuth = [
StartLogin=StartLogin,
FinishLogin=FinishLogin,
Refresh=Refresh,
Logout=Logout
]
],

Label = Extension.LoadString("DataSourceLabel")
];


// Data Source UI publishing description
System.Publish = [
Beta = true,
Category = "Other",
ButtonText = { Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp") },
LearnMoreUrl = "https://powerbi.microsoft.com/", //This can be replaced with our System URI. This is a help URI which gives more info about this connector.
SourceImage = System.Icons,
SourceTypeImage = System.Icons
];

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

//Function that extracts the access_token and other properties related to the OAuth flow.:
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;

//Function that retrieves a new access token from a refresh token.
//Refresh definition:
Refresh = (resourceUrl, refresh_token) => TokenMethod("authorization_code", "code", refresh_token);

//Function that invalidates the user's current access token:
//Logout definition:
Logout = (token) => logout_uri;

//Below definition is to exchange an auth code for an access token:
TokenMethod = (grantType, tokenField, code) =>
let
queryString = [
client_id = client_id,
grant_type = "authorization_code", //grantType, //"authorization_code", //This can also be grant_type
scope = "offline_access " & GetScopeString(scopes, scope_prefix),//Optional
redirect_uri = redirect_uri
//client_id = client_id

],
queryWithCode = Record.AddField(queryString, tokenField, code),

tokenResponse = Web.Contents(token_uri, [
Content = Text.ToBinary(Uri.BuildQueryString(queryWithCode)),
Headers = [
//#"Authorization" = "Basic XXXXXXXXXXX encoded client key and secrect",
#"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;

Value.IfNull = (a, b) => if a <> null then a else b;

GetScopeString = (scopes as list, optional scopePrefix as text) as text =>
let
prefix = Value.IfNull(scopePrefix, ""),
addPrefix = List.Transform(scopes, each prefix & _),
asText = Text.Combine(addPrefix, " ")
in
asText;


System.Icons = [
Icon16 = { Extension.Contents("System16.png"), Extension.Contents("System20.png"), Extension.Contents("System24.png"), Extension.Contents("System32.png") },
Icon32 = { Extension.Contents("System32.png"), Extension.Contents("System40.png"), Extension.Contents("System48.png"), Extension.Contents("System64.png") }
];

 

I'm building this code without the need of Client Secret and I have a client_id.txt file which contains my clientid. I also have the API username and password but cannot figure out how to use it within this code. I've tried using the UsernameLabel and PasswordLabel(https://docs.microsoft.com/en-us/power-query/handlingauthentication)l but the datasource doesn't accept this format.

 

This is how we used it in our old powershell code:

 

# Get the bearer token from AAD B2C using ROPC flow
$bearerBody = @{
client_id="xxxxxxxxxxxxxxx"
scope="yyyyyyyyyyyyyyyyyyyyy"
grant_type="password"
response_type="token"
username="abc123"
password="**********"
}

 
I want to use the API username and password with the Oauth flow to successfully connect to our cloud environment. Appreciate if you could help. 
Anonymous
Not applicable

Hi 

 

Does anyone have a suggestion on how to solve this error?

 

Appreciate your response. 

 

Thanks

AfsarP1

Anonymous
Not applicable

Hi Maggie

 

I'm building a code to connect to our cloud. I've looked at Jussi's code and also codes from Matt Mason on Github(MyGraph in particular) and built the below code:

 

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

 

client_id = Text.FromBinary(Extension.Contents("client_id.txt"));
redirect_uri = "https://ourdomain/oauth2/authresp";
token_uri = "https://ourdomain/oauth2/v2.0/token"; //Used to retrieve an access token
authorize_uri = "https://ourdomain/oauth2/authorize";
logout_uri = "https://login.microsoftonline.com/logout.srf";

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

// OAuth2 scope
scope_prefix = "https://ourdomian.com";
scopes = {
"daily",
"User.Read",
"openid"
//".Read.All",
//"IdentityProvider.Read.All"
//"client_id"

//It can be delegated permission or app permission https://docs.microsoft.com/en-us/graph/auth/auth-concepts#microsoft-graph-permissions
};

[DataSource.Kind="System", Publish="System.Publish"]
shared System.Contents = (url as text) =>

let
source = Json.Document(Web.Contents(url)) //If the data is returned from the datasource in JSON format

in
source;

// Data Source Kind description
System = [
TestConnection = (dataSourcePath) => { "System.Contents", dataSourcePath },
Authentication = [
OAuth = [
StartLogin=StartLogin,
FinishLogin=FinishLogin,
Refresh=Refresh,
Logout=Logout
]
],

Label = Extension.LoadString("DataSourceLabel")
];


// Data Source UI publishing description
System.Publish = [
Beta = true,
Category = "Other",
ButtonText = { Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp") },
LearnMoreUrl = "https://powerbi.microsoft.com/", //This can be replaced with our System URI. This is a help URI which gives more info about this connector.
SourceImage = System.Icons,
SourceTypeImage = System.Icons
];

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

//Function that extracts the access_token and other properties related to the OAuth flow.:
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;

//Function that retrieves a new access token from a refresh token.
//Refresh definition:
Refresh = (resourceUrl, refresh_token) => TokenMethod("authorization_code", "code", refresh_token);

//Function that invalidates the user's current access token:
//Logout definition:
Logout = (token) => logout_uri;

//Below definition is to exchange an auth code for an access token:
TokenMethod = (grantType, tokenField, code) =>
let
queryString = [
client_id = client_id,
grant_type = "authorization_code", //grantType, //"authorization_code", //This can also be grant_type
scope = "offline_access " & GetScopeString(scopes, scope_prefix),//Optional
redirect_uri = redirect_uri
//client_id = client_id

],
queryWithCode = Record.AddField(queryString, tokenField, code),

tokenResponse = Web.Contents(token_uri, [
Content = Text.ToBinary(Uri.BuildQueryString(queryWithCode)),
Headers = [
//#"Authorization" = "Basic XXXXXXXXXXX encoded client key and secrect",
#"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;

Value.IfNull = (a, b) => if a <> null then a else b;

GetScopeString = (scopes as list, optional scopePrefix as text) as text =>
let
prefix = Value.IfNull(scopePrefix, ""),
addPrefix = List.Transform(scopes, each prefix & _),
asText = Text.Combine(addPrefix, " ")
in
asText;


System.Icons = [
Icon16 = { Extension.Contents("System16.png"), Extension.Contents("System20.png"), Extension.Contents("System24.png"), Extension.Contents("System32.png") },
Icon32 = { Extension.Contents("System32.png"), Extension.Contents("System40.png"), Extension.Contents("System48.png"), Extension.Contents("System64.png") }
];

 

I'm building this code without the need of Client Secret and I have a client_id.txt file which contains my clientid. I also have the API username and password but cannot figure out how to use it within this code. I tried using the UsernameLabel and PasswordLabel(https://docs.microsoft.com/en-us/power-query/handlingauthentication)l but the datasource doesn't accept this format.

 

This is how we used it in our old powershell code:

 

# Get the bearer token from AAD B2C using ROPC flow
$bearerBody = @{
client_id="xxxxxxxxxxxxxxx"
scope="yyyyyyyyyyyyyyyyyyyyy"
grant_type="password"
response_type="token"
username="abc123"
password="**********"
}

 

How can modify my code to use the API username and password?

 

Thanks 

AfsarP1

Helpful resources

Announcements
Power BI DataViz World Championships

Power BI Dataviz World Championships

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now!

December 2025 Power BI Update Carousel

Power BI Monthly Update - December 2025

Check out the December 2025 Power BI Holiday Recap!

FabCon Atlanta 2026 carousel

FabCon Atlanta 2026

Join us at FabCon Atlanta, March 16-20, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.

Top Solution Authors