公开refreshtoken API是不是安全

Posted

技术标签:

【中文标题】公开refreshtoken API是不是安全【英文标题】:Is it safe to expose refreshtoken API公开refreshtoken API是否安全 【发布时间】:2022-01-02 13:04:26 【问题描述】:

我有一个在前端使用 React 并在后端使用 ASP.Net Web API 开发的应用程序。我正在使用 JWT 进行授权。过程是

    当用户登录并通过身份验证时,会向前端发送 2 个令牌,访问令牌和刷新令牌。访问令牌是 JWT,刷新令牌是随机字符串,刷新令牌存储在数据库中。 对于每次对 API 访问令牌的后续调用都附加在标头中,我有一个身份验证过滤器来验证访问令牌。 访问令牌过期后,将引发 401 状态并显示错误消息 TokenExpired。 前端收到401后,调用刷新令牌API获取刷新令牌

我的问题是我不能有一个身份验证过滤器来验证刷新令牌 API 的访问令牌,因为它会由于访问令牌过期而抛出 401,所以我需要将刷新令牌 API 设为匿名所以它未命中身份验证过滤器。如果我匿名,我将调用数据库以获取为用户存储的刷新令牌,并将其与我从前端收到的令牌进行比较。那么让刷新令牌 API 匿名是否安全,如果不是最好的方法是什么?

【问题讨论】:

当您验证访问令牌时,您是否使用来自 JWKS 的公钥来检查签名?如果是这样,它是一个公钥,任何人都可以使用公钥(来自 JWKS 公共 URL 的 RSA/ECDSA)创建任何 JWT 的签名。因此,如果访问令牌是公共的,则不应将其用于身份验证。如果您验证 HMAC签名,那么 JWT 的签名是使用预共享密钥完成的,应该被认为对 auth 敏感,并且通过扩展刷新等于访问令牌。你使用什么样的 JWT,它是做什么用的?跨度> JWT 使用预共享密钥进行签名。由于后端是REST API,无状态,所以jwt用于授权和构造主体对象。 @stof 错误,您无法使用公钥签署令牌。令牌使用私钥签名并使用公钥验证。这也不是 OP 的问题。 其他帖子提到的简单步骤:***.com/questions/27726066/jwt-refresh-token-flow @Jps 是正确的,不同意规范。您指的是 HMAC 变体,它需要一个您可能认为是私钥的预共享密钥,但规范设计 RSA/ECDSA 是为了加密。因此,只有一方可以持有私钥并且永远不会共享它,这意味着一方只能创建签名,如果他们没有私钥,另一方无法重新创建该签名 fkr 验证.. 这是荒谬的.私钥用于解密,共享密钥用于签署 HMAC,或者公钥用于签署加密令牌声明 【参考方案1】:

在 Auth0,创建了一组功能,通过对其生命周期实施保护和控制来降低与使用刷新令牌相关的风险。我们的身份平台提供刷新令牌轮换,还带有自动重用检测功能。

请阅读以下主题。

Refresh Token Rotation

Refresh Token Automatic Reuse Detection

【讨论】:

我们正在进行刷新令牌轮换。当请求新的访问令牌时,我们使用刷新令牌进行验证并提供新的访问令牌和新的刷新令牌,并且刷新令牌在数据库中更新。但是我不认为我们可以存储到目前为止生成的所有刷新令牌的列表,如自动重用检测中提到的那样【参考方案2】:

使用预共享密钥对 JWT 进行签名。由于后端是REST API,并且是无状态的,所以jwt用于授权和构造主体对象

正如您所说,访问令牌代表您的应用程序中的授权,如果刷新令牌被暴露,那么刷新令牌可以由不良行为者提供以获得他们可以用于相同授权的访问令牌。

使用“预共享密钥”表示 JWT 是 JWT 的唯一 HMAC 变体,即没有加密,因为这表明私钥和公钥对与“预共享密钥”相对。因此,JWT 本质上是一个签名,用于我们确保完整性的安全特性,即 JWT 的声明格式正确,并且自签名后未更改。这也意味着在一端用于签名的秘密与在另一端用于验证的秘密相同,必须使用相同的秘密,因为验证签名需要两端都生成签名并且签名匹配。所以没有数据被加密,所以 JWT 中的数据不是敏感的,需要保护。

在这种情况下,刷新和访问令牌都是一个简单的 JWT,只能由密钥的持有者生成 - 如果它们被暴露,只要它们保持有效,它们就可以用来发出恶意请求 (@987654322 @声明)。

基本上这种类型的 JWT 可能会被滥用,如果暴露来冒充签署 JWT 的秘密所代表的身份,而实际上并不知道秘密本身,直到 nbf 声明使令牌过期 - 并且刷新令牌是一种机制在没有秘密的情况下扩展 nbf 声明(这将产生新的签名,因为 nbf 声明在使用时会改变)。

访问令牌重用有一种保护措施,即 nonce 声明。如果您当前不使用 nonce 声明,您可以阅读有关 OIDC 如何实现并在您的应用程序中执行相同操作的信息。但是正如您所说,您的应用程序是无状态的,但希望后端具有一种状态形式,以确保没有随机数重用并防止 JWT 签名重用。对于每个随机数,JWT 签名都会更改,因此访问令牌会更改并且只能使用 1 次。所以如果被盗,是一种先用代币的竞态条件,极大地降低了风险,但不是完美的解决方案。

【讨论】:

以上是关于公开refreshtoken API是不是安全的主要内容,如果未能解决你的问题,请参考以下文章

向公众公开 Firebase apiKey 是不是安全?

向公众公开 Firebase apiKey 是不是安全?

向公众公开 Firebase apiKey 是不是安全?

API 密钥是不是通过 get 请求公开?

如何在 Spring Boot 中同时公开 SOAP Web 服务和 RESTful API?

公开会话的 CSRF 保护令牌是不是安全?