从客户端应用发送请求以获取访问令牌的理想/安全方法是什么?
我有一个REST API(使用Spring Boot开发),由该API的客户端应用程序(使用React.js开发)使用。例如,Stackoverflow具有后端API,其前端客户端使用该API。 REST API使用OAuth2保护。
API返回访问令牌的端点是
http://192.168.43.70:8085/api/v1/oauth/token?grant_type=password&username=22@gmail.com&password=mypassword
以及客户机密。这是React.js的请求:
axios
.create({
baseURL:
"http://192.168.43.70:8085/api/v1/oauth/token?grant_type=password&username=22@gmail.com&password=mypassword",
auth: {
username: "my-client",
password: "ZS10ZXN0"
}
})
这是正确的方法,因为我们将客户端机密("my-client"
,"bGl2ZS10ZXN0"
)暴露给浏览器,因此任何人都可以从中看到用于此请求的客户端凭据?
答案 0 :(得分:3)
您是正确的,这是不安全的,不建议这样做。最好使用不需要客户端凭据的其他授权流程。
我建议您看一下authorization_code
授予流程(没有客户端密码),而不是密码授予流程。 couple中有一个resources,将为您提供更多为何不使用密码流的背景知识,但简要介绍一下:
单页应用程序(或基于浏览器的应用程序)在从网页加载Javascript和HTML源代码后完全在浏览器中运行。由于浏览器可以使用整个源,因此它们无法维护客户端机密的机密性,因此这些应用程序不使用该机密。 流与授权码流完全相同,但是在最后一步,无需使用客户端机密就将授权码交换为访问令牌。
但是,更好的是,如果您可以引入一个服务器端组件,该组件可以通过JSESSIONID(暗示更改为会话后端)与客户进行协商,那么我相信您会发现secrets are much easier to maintain on the backend。您可以为此查看Spring Security's OAuth 2.0 Client support。
答案 1 :(得分:2)
资源所有者密码凭据授予不是您应用程序的正确授予类型,请参见RFC 6749:
4.3。资源所有者密码凭据授予
资源所有者密码凭证授予类型适用于资源所有者与客户端具有信任关系的情况,例如设备操作系统或高特权应用程序。授权服务器在启用此授予类型时应格外小心,仅在其他流程不可行时才允许它。
您可以使用隐式授予,请参见RFC 6749:
4.2。隐式授予
隐式授予类型用于获取访问令牌(它不支持发布刷新令牌),并且已针对已知操作特定重定向URI的公共客户端进行了优化。这些客户端通常是在浏览器中使用脚本语言(例如JavaScript)实现的。
[...]
隐式授予类型不包括客户端身份验证,而是依赖于资源所有者的存在和重定向URI的注册。由于访问令牌已编码到重定向URI中,因此它可能会暴露给资源所有者和驻留在同一设备上的其他应用程序。
,但是由于安全问题,某些授权服务器不支持它。 Spring Security OAuth2支持它。
尽管它已为机密客户端进行了优化,但您也可以使用授权码授予,请参阅RFC 6749:
4.1。授权码授予
授权码授予类型用于获取访问令牌和刷新令牌,并且针对机密客户端进行了优化。
[...]
如果客户端类型为机密或向客户端颁发了客户端凭据(或分配了其他身份验证要求),则客户端必须按照第3.2.1节中的说明,通过授权服务器进行身份验证。
,但是由于安全问题,某些授权服务器不支持它。 Spring Security OAuth2的默认配置需要客户端身份验证。
另一种方法是使用PKCE进行授权代码授予,请参见RFC 7636:
OAuth公共客户端用于代码交换的证明密钥
摘要
利用授权代码授予的OAuth 2.0公共客户端容易受到授权代码拦截攻击的攻击。该规范描述了攻击以及通过使用代码交换证明密钥(PKCE,发音为“ pixy”)减轻威胁的技术。
但是Spring Security不支持它,请参阅4943。