JSL / JMP 17:OAuth 显然生成了无效请求我目前正在尝试获取 OAuth2 令牌来对外部服务(Snowflake 数据库)进行身份验证,但是遇到了一些问题。
根据文档,这应该可以工作:
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 />);
但是,每当我运行这个程序时,我都会收到一个 HTTP/1.1 400 Bad Request INVALID_REQUEST:INVALID_REQUESTDESCRIPTION
为了调试这个问题,我启动了一个本地运行的 HTTP 回显服务器,并从 Python(工作代码,已通过真实的 OAuth2 服务器验证)和 JMP 发送请求,然后我得到了以下回复:
Python
127.0.0.1 - - [05/Feb/2025 13:36:00] "POST / HTTP/1.1" 200 -
主机:localhost:8008
用户代理:python-requests/2.32.3
接受编码:gzip,deflate
接受: */*
连接:保持连接
内容长度:91
内容类型:application/x-www-form-urlencoded
授权:基本=
grant_type=密码&用户名= &密码= &scope=session%3Arole-any
JMP17
127.0.0.1 - - [05/Feb/2025 13:36:56] "POST / HTTP/1.1" 200 -
主机:localhost:8008
用户代理:libcurl-agent/1.0(Windows NT 10.0.22631;x64)
接受: */*
内容长度:102
内容类型:application/x-www-form-urlencoded
客户端ID= &redirect_uri=&response_type=token&范围=&状态=
如您所见,没有授权标头,并且大多数请求参数(授予类型、用户名、密码、范围)都缺失。
在我看来,JMP 似乎生成了一个虚假请求,因此与服务器的通信失败。这个假设正确吗?还是我做错了什么?
任何帮助都将非常感激。
亲切的问候
坦率
自动化和脚本回复:JSL / JMP 17:OAuth 显然生成了无效请求@bryan_boone
不确定这些链接是否有用,但使用 HTTP 请求将 Google Drive 与 JMP 集成可能会提供一些想法。另请查看脚本索引中的获取授权标头 + 新 OAuth2(bryan 在这里提到了这些https://community.jmp.com/t5/Discussions/Open-file-from-private-github-repository-authentication-needed/mp/777304/highlight/true#M95860 )。JSL 语法参考中还有更多文档,但不知道这是否有用https://www.jmp.com/support/help/en/18.1/#page/jmp/utility-functions.shtml?os=win&source=application#ww7957559
回复:JSL / JMP 17:OAuth 显然生成了无效请求是的,
新 OAuth2
是可行的方法。我看看是否可以将 New OAuth2 Token 用作它的别名。
如果没有,我将弃用新的 OAuth2 令牌。
新的 OAuth2 为您完成所有浏览器握手。
回复:JSL / JMP 17:OAuth 显然生成了无效请求谢谢,New OAuth2() 看起来好多了。我成功地通过“客户端凭据”流程获取了刷新令牌。
但是,我很难让密码流程正常工作。我当前的代码如下所示:
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>但是,这会导致 HTTP/1.1 401 未授权。
为了进行比较,这里有一个 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"]我猜是因为 JMP 没有使用 client_id / client_secret 建立 HTTP Basic 身份验证。我做错了什么?
回复:JSL / JMP 17:OAuth 显然生成了无效请求我认为你正在谈论的是:
https://oauth.net/2/grant-types/password/
这次讨论(关于参考)表明已经远离了这一点。
您可能可以使用 HTTPRequest(无需 New OAuth2)完成所有操作,因为无需使用密码授予类型进行提示(即,它直接针对令牌 URL)
我认为等效的 JSL(对于 python)看起来像这样,但我无法测试它。
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>
回复:JSL / JMP 17:OAuth 显然生成了无效请求经过一番调整,我让它工作了;根据你的建议,关键的改变如下:
- 包括基本身份验证
- 使用表单编码而不是 JSON(虽然不能 100% 确定为什么 JSON 不起作用)
工作示例:
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>
就目前而言,这是可以的(我们使用技术用户,因此不需要获取用户的个人密码),但我们肯定会研究更安全的方法。
非常感谢您的帮助!
回复:JSL / JMP 17:OAuth 显然生成了无效请求很棒的发现!我不太确定我引入了哪 17 个授权方法(可能是维护?)
回复:JSL / JMP 17:OAuth 显然生成了无效请求小小的(但重要的)更正:看来我的方法只适用于 JMP 18,而不适用于 JMP 17。
显然,“授权方法”仅在 JMP 18 中引入。当尝试在 JMP 17 中使用该方法时,我得到:
访问或评估‘身份验证方法’时出现无法识别的消息,身份验证方法(“BASIC”)/*###*/
我重新检查了文档:
- JMP 17 文档中根本没有提及“身份验证方法”
- JMP 18 文档包含PI 调用中“身份验证方法”的一个示例
(我之前没有注意到这一点,因为显然,我的 JMP 18 测试中的令牌存储在 JMP 文件/数据表中,因此,JMP 17 很乐意使用旧令牌,即使它自己尝试获取新令牌失败了)