Forum Discussion
RICRUS
3 years agoNew Member
verb-type error for OAuth connector
I am trying to build an OAuth2 connector using the standard boilerplate template with VSCode Power Query SDK.
When I run 'Set credential' I am presented with the login screen modal as expected. But after successfully logging into my application I get a 'verb-type' error returned. I am not sure why this is? Can anyone see any issues with my code?
I am running Windows 11 (ARM) - if that helps.
The error:
Unhandled Exception: System.Net.ProtocolViolationException: Cannot send a content-body with this verb-type.
at Microsoft.Mashup.Engine1.Runtime.Extensibility.ExtensionOAuthFactory.Provider.Microsoft.Mashup.OAuth.IOAuthProvider.FinishLogin(Byte[] serializedContext, Uri callbackUri, String state)
at PQTest.Common.Commands.<>c__DisplayClass11_0.<SetCredentalInteractive>b__0()
at PQTest.Common.Commands.ConfigureMashupEnvironmentAndRun(Configuration configuration, Action action)
at PQTest.Console.Program.RunCredentialCommand(CommandLineApplication app, CommandLineApplication command, Action`1 invoke, DataSourceSetting dataSourceSetting)
at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
at PQTest.Console.Program.Main(String[] args)
My code:
// This file contains your Data Connector logic
section MyConnector;
// OuraCloud OAuth2 values
client_id = Text.FromBinary(Extension.Contents("client_id.txt"));
client_secret = Text.FromBinary(Extension.Contents("client_secret.txt"));
redirect_uri = "https://oauth.powerbi.com/views/oauthredirect.html";
token_uri = "http://mydomain.com/oauth2/token";
authorize_uri = "http://mydomain.com/v2/oauth2/authorize";
logout_uri = "https://login.microsoftonline.com/logout.srf";
// Login modal window dimensions
windowWidth = 720;
windowHeight = 1024;
// OAuth2 scope
scope_prefix = "";
scopes = {
"daily"
};
[DataSource.Kind="MyConnector", Publish="MyConnector.Publish"]
shared MyConnector.Contents = (url as text) =>
let
source = Json.Document(Web.Contents(url))
in
source;
// Data Source Kind description
MyConnector = [
TestConnection = (dataSourcePath) => { "MyConnector.Contents", dataSourcePath },
Authentication = [
OAuth = [
StartLogin=StartLogin,
FinishLogin=FinishLogin,
Refresh=Refresh,
Logout=Logout
]
],
Label = Extension.LoadString("DataSourceLabel")
];
// Data Source UI publishing description
MyConnector.Publish = [
Beta = true,
Category = "Other",
ButtonText = { Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp") },
LearnMoreUrl = "https://powerbi.microsoft.com/",
SourceImage = MyConnector.Icons,
SourceTypeImage = MyConnector.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,
state = state,
scope = GetScopeString(scopes, scope_prefix)
])
in
[
LoginUri = authorizeUrl,
CallbackUri = redirect_uri,
WindowHeight = 720,
WindowWidth = 1024,
Context = null
];
FinishLogin = (context, callbackUri, state) =>
let
parts = Uri.Parts(callbackUri)[Query],
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;
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;
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;
MyConnector.Icons = [
Icon16 = { Extension.Contents("MyConnector16.png"), Extension.Contents("MyConnector20.png"), Extension.Contents("MyConnector24.png"), Extension.Contents("MyConnector32.png") },
Icon32 = { Extension.Contents("MyConnector32.png"), Extension.Contents("MyConnector40.png"), Extension.Contents("MyConnector48.png"), Extension.Contents("MyConnector64.png") }
];
The error was caused by `token_uri` and `authorize_uri` being called over HTTP and not HTTPS.
1 Reply
- RICRUSNew Member
The error was caused by `token_uri` and `authorize_uri` being called over HTTP and not HTTPS.