JSL / JMP 17: OAuth apparently generates invalid requestI'm currently trying to obtain an OAuth2 token to authenticate for an external service (Snowflake database), but I'm running into some problems with this.
According to the documentation, this is supposed to work:
oauth2_token = New OAuth2 Token(<BR /> User( username ),<BR /> Password( password),<BR /> Client ID( client_id ),<BR /> Client Secret( client_secret ),<BR /> Token URL( "http://localhost:8008" ),<BR /> Grant Type("password"),<BR /> Scope("session:role-any")<BR />);
However, whenever I run this, I get back an HTTP/1.1 400 Bad Request INVALID_REQUEST:INVALID_REQUESTDESCRIPTION
To debug this, I started a locally running HTTP echo server and sent requests from Python (working code, verified with real OAuth2 server) and JMP, and I got back this:
Python
127.0.0.1 - - [05/Feb/2025 13:36:00] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: python-requests/2.32.3
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 91
Content-Type: application/x-www-form-urlencoded
Authorization: Basic =
grant_type=password&username=&password=&scope=session%3Arole-any
JMP 17
127.0.0.1 - - [05/Feb/2025 13:36:56] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: libcurl-agent/1.0 (Windows NT 10.0.22631;x64)
Accept: */*
Content-Length: 102
Content-Type: application/x-www-form-urlencoded
client_id=&redirect_uri=&response_type=token&scope=&state=
As you can see, there's no Authorization header, and also, most of the request parameters (grant type, username, password, scope) are missing.
To me, it looks like JMP generates a bogus request, and therefore, the communication with the server fails. Is this assumption correct? Or am I doing something wrong?
Any help would be highly appreciated.
Kind regards
Frank
Automation and ScriptingRe: JSL / JMP 17: OAuth apparently generates invalid request@bryan_boone
Not sure if these links will be helpful but Integrating Google Drive with JMP using HTTP Request might give some ideas. Also check out Get Authorization Header + New OAuth2 from Scripting Index (bryan mentioned these here https://community.jmp.com/t5/Discussions/Open-file-from-private-github-repository-authentication-needed/m-p/777304/highlight/true#M95860). There is also a bit more documentation in JSL Syntax Reference but no idea if this helpful at all https://www.jmp.com/support/help/en/18.1/#page/jmp/utility-functions.shtml?os=win&source=application#ww7957559
Re: JSL / JMP 17: OAuth apparently generates invalid requestYes,
New OAuth2
is the way to go. I look to see if I can alias New OAuth2 Token to it.
If not, I'll deprecate New OAuth2 Token.
New OAuth2 does all the browser handshaking for you.
Re: JSL / JMP 17: OAuth apparently generates invalid requestThanks, New OAuth2() looks much better. I was successfully able to obtain a Refresh token with the "Client Credentials" flow.
However, I'm struggling with getting the Password flow to work. My current code looks like this:
client_id = "<REDACTED>";
client_secret = "<REDACTED>";
token_url = "https://someurl/token";
auth_url = "https://someurl/auth";
username = "<REDACTED>";
password = "<REDACTED>";
grant_type = "password";
scope = "session:role-any";
auth_fields = [=> ];
token_fields = [=> ];
oauth2 = New OAuth2();
oauth2 << Grant Type( "Password" );
oauth2 << Auth URL( auth_url );
oauth2 << Token URL( token_url );
oauth2 << Username(username);
oauth2 << Password(password);
auth_fields["scope"] = scope;
auth_fields["client_id"] = client_id;
token_fields["client_secret"] = client_secret;
oauth2 << Auth Fields( auth_fields );
oauth2 << Token Fields( token_fields );</REDACTED></REDACTED></REDACTED></REDACTED>However, this results in HTTP/1.1 401 Unauthorized.
For comparison, here's a working example in Python:
def get_token(username: str, password: str, client_secret: str) -> str:
client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, client_secret)
post_data = {
"grant_type": "password",
"username": username,
"password": password,
"scope": "session:role-any",
}
response = requests.post(TOKEN_URL, auth=client_auth, data=post_data)
token_json = response.json()
print(f"Got token: {token_json}")
return token_json["access_token"]I guess that somehow, JMP doesn't establish the HTTP Basic auth with client_id / client_secret. What am I doing wrong?
Re: JSL / JMP 17: OAuth apparently generates invalid requestI think you are talking about:
https://oauth.net/2/grant-types/password/
This discussion (on the reference) says there's a move away from this.
You can probably do it all with HTTPRequest (without New OAuth2) since there is no need to prompt using password grant type (ie, it goes directly against the token URL)
The equivalent JSL (to the python) I believe looks like this, but I can't test it.
client_id = "<REDACTED>";
client_secret = "<REDACTED>";
token_url = "https://someurl/token";
username = "<REDACTED>";
password = "<REDACTED>";
grant_type = "password";
scope = "session:role-any";
payload =[=>];
payload["grant_type"] = "password";
payload["username"] = username;
payload["password"] = password;
payload["scope"] = scope;
request = New HTTP Request(
URL(token_url),
Username(client_id),
Passwordlient_id),
JSON(payload)
);
data = request << Send();
json = ParseJSON(data);</REDACTED></REDACTED></REDACTED></REDACTED>
Re: JSL / JMP 17: OAuth apparently generates invalid requestWith some fiddling, I got it to work; key changes from your suggestion:
- include Basic Auth
- use Form encoding instead of JSON (not 100% sure why JSON didn't work, though)
Working example:
client_id = "<REDACTED>";
client_secret = "<REDACTED>";
token_url = "https://someurl/token";
username = "<REDACTED>";
password = "<REDACTED>";
grant_type = "password";
scope = "session:role-any";
request = New HTTP Request(
Method("POST"),
URL(token_url),
Username(client_id),
Password(client_secret),
Form(
Fields([[
"grant_type" => grant_type,
"username" => username,
"password" => password,
"scope" => scope
]]
)
)
);
request << Authentication Method( "BASIC" );
data = request << Send();
json = ParseJSON(data);</REDACTED></REDACTED></REDACTED></REDACTED>
For the time being, that's ok (we're using a technical user, so no need to get the user's personal password), but we'll definitely look into more secure approaches.
Thanks a lot for your help!
Re: JSL / JMP 17: OAuth apparently generates invalid requestGreat find! I wasn't quite sure which 17 I introduced Authorization Method (maybe a maintenance?)
Re: JSL / JMP 17: OAuth apparently generates invalid requestSmall (but important) correction: it seems my approach only works with JMP 18, not with JMP 17.
Apparently, "Authorization Method" was introduced only in JMP 18. When trying to use the approach in JMP 17, I get:
Unrecognized message in access or evaluation of 'Authentication Method' , Authentication Method( "BASIC" ) /*###*/
I re-checked the documentation:
- the JMP 17 docs contain no mention of "Authentication Method" whatsoever
- the JMP 18 docs contain one example of "Authentication Method" in a PI call
(I hadn't noticed this before because apparently, the token from my JMP 18 tests was stored inside the JMP file / data table, and therefore, JMP 17 happily used the old token even though its own attempt to obtain a new one failed)