OAuth2 (Okta) 令牌生成失败,出现 401 未授权响应 - client_credentials 授权类型

OAuth2 (Okta) token generation fails with 401 unauthorized response - client_credentials grant type

我 运行 遇到一个问题,我的 AJAX 请求在尝试获取 OAuth2 (Okta) 令牌时失败,错误代码为 401 - 未经授权。

预览标签显示错误如下:

Browser requests to the token endpoint must use Proof Key for Code Exchange

这是否意味着我不能将 client_credentials g运行t 类型用于客户端请求?

这是我的 AJAX 请求:

$.ajax({
    url: dataParsed.TokenServiceEndpoint,
    type: "POST",
    contentType: "application/x-www-form-urlencoded",
    datatype: "application/json",
    headers: {
        "Authorization": "Basic " + btoa(dataParsed.TokenServiceUser + ":" + dataParsed.TokenServicePassword)
    },
    data: {
        "grant_type": "client_credentials"
    }
}

类似的请求可以使用 postman,但我不确定两者之间有什么区别,或者如何通过 ajax.

使其工作

这是从 Postman 导出的请求:

Content-Type: application/x-www-form-urlencoded
Authorization: Basic *************
User-Agent: PostmanRuntime/7.29.0
Accept: */*
Postman-Token: fd2c4617-a4bb-4d28-88bd-1aa84c2a7404
Host: *****
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 29
Cookie: JSESSIONID=3B62F82EE85BC8574756101635CC3B14
 
grant_type=client_credentials
 
HTTP/1.1 200 OK
Date: Fri, 18 Mar 2022 14:41:42 GMT
Server: nginx
Content-Type: application/json
x-okta-request-id: YjSaJqln-TB3pOn9kgwmsQAABSw
x-xss-protection: 0
p3p: CP="HONK"
x-rate-limit-limit: 20000
x-rate-limit-remaining: 19971
x-rate-limit-reset: 1647614537
cache-control: no-cache, no-store
pragma: no-cache
expires: 0
expect-ct: report-uri="*****", max-age=0
x-content-type-options: nosniff
Strict-Transport-Security: max-age=315360000; includeSubDomains
X-Robots-Tag: noindex,nofollow
set-cookie: sid=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
set-cookie: autolaunch_triggered=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
set-cookie: JSESSIONID=AA2D48FFC46A8AC0E1D139D038CE98AB; Path=/; Secure; HttpOnly
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked

使用 Fiddler 跟踪您的请求,Okta 也不支持来自浏览器的客户端凭据,必须在服务器级别。 检查这个 - https://support.okta.com/help/s/article/Browser-requests-to-the-token-endpoint-must-use-Proof-Key-for-Code-Exchange?language=en_US

我说使用 Fiddler 进行跟踪的原因是,当使用邮递员与来自 ajax 时,您可以确认是否正在发送来源 header,因此,确认您是 运行里面提到的问题link我贴了。

客户端凭据授予用于 server-to-server 通信。它允许您的客户端在授权服务器上进行身份验证以获取访问令牌。这意味着您需要一个机密客户端才能成功使用此流程 - 一个拥有秘密并可以使用该秘密进行身份验证的客户端。浏览器客户端(例如 SPA)无法保守秘密——任何人都可以从您的代码中读取秘密。这就是 Okta 不允许您直接从浏览器使用客户端凭据的原因。错误响应告诉您浏览器客户端必须使用 PKCE,并且由于 PKCE 只能在授权代码流中使用,这隐含地意味着 Okta 只允许来自浏览器客户端的授权代码流。

Postman 不是浏览器,这就是 Postman 的请求有效的原因。如果你从 curl 运行 它也会工作。

总而言之,您不必使用浏览器的客户端凭据。如果您只是为了开发目的或解决问题而需要它,您可以 运行 来自邮递员的流程并将令牌粘贴到您的前端代码中。在生产代码中,您应该使用授权代码流。不过,您应该记住,此流程需要用户交互。