JWT(Json Web Token)的受众“aud”与客户端ID的区别是什么?

195
我正在实现OAuth 2.0 JWT访问令牌在我的身份验证服务器中。但是,我不清楚JWT的aud声明和client_id HTTP头值之间的区别是什么。他们相同吗?如果不是,请解释一下两者之间的区别。
我的猜测是,aud应该指向资源服务器,而client_id应该指向身份验证服务器识别的客户端应用程序之一(即Web应用程序或iOS应用程序)。
在我目前的情况下,我的资源服务器也是我的Web应用程序客户端。

可能会有帮助!实际上,我试图弄清楚“受众”是什么,结果发现“客户端ID”也是我的“受众”。(这取决于Keycloak管理员中的配置。) - Praveen
如果您使用的是OIDC而不是OAuth,则答案是不同的--请向下滚动查看@joseph-a的答案。 - Noumenon
4个回答

243

事实证明,我的怀疑是正确的。JWT中的aud声明是指应接受令牌的资源服务器。

正如这篇文章所述:

令牌的受众是令牌的预期接收者。

受众值是一个字符串--通常是正在访问的资源的基地址,例如https://contoso.com

OAuth中的client_id是指将请求来自资源服务器的资源的客户端应用程序。

客户端应用程序(例如您的iOS应用程序)将从身份验证服务器请求JWT。在此过程中,它传递了它的client_idclient_secret以及可能需要的任何用户凭据。授权服务器使用client_idclient_secret验证客户端并返回JWT。

JWT将包含一个aud声明,指定JWT有效的资源服务器。如果aud包含www.myfunwebapp.com,但客户端应用程序试图在www.supersecretwebapp.com上使用JWT,则将拒绝访问,因为该资源服务器将看到JWT不是为其而设计的。


10
似乎 aud 也可能是 client_id。请参阅 https://tools.ietf.org/id/draft-hunt-oauth-v2-user-a4c-01.txt 中的说明:aud 在 session_token 中是必需的,包含接收断言的客户端的 client_id。 - themihai
1
资源服务器不知道客户端发送JWT的位置。资源服务器如何拒绝从您的iOS应用程序发送到其他URL的此类流量?我认为你是不正确的。 - John Korsnes
4
RFC表示受众(aud)标识接收者。接收者接收您的JWT令牌。如果您有一个Web应用程序,那么这可能是https://contoso.com/,但如果您有一些桌面或移动应用程序(进行身份验证),则受众没有任何URI。发行人是生成JWT令牌的人,因此最可能是服务器的地址。RFC表示此声明的使用是可选的,因此只在需要时使用它。 - Konrad
3
其实我很困惑受众和发行人之间的区别是什么。 - Andy
3
@Andy Issuer指的是授权服务器,而audience则指的是资源服务器。有时候,它们可以是同一个服务器,但并非总是如此。例如,如果您使用Google账号登录到一个Web应用程序,那么Google将处理授权,您是资源所有者,而您的资源由Web应用程序提供服务。 - mrpandey
显示剩余2条评论

117

JWT的“aud”(受众)声明

根据RFC 7519

“aud”(受众)声明标识了JWT的接收方。每个要处理JWT的主体都必须在受众声明中使用一个值来识别自己。如果处理声明的主体在此声明存在时没有使用一个值来识别自己,则JWT必须被拒绝。通常情况下,“aud”值是包含StringOrURI值的大小写敏感字符串数组。当JWT只有一个受众时,“aud”值可以是包含StringOrURI值的单个大小写敏感字符串。 受众值的解释通常是应用程序特定的。 使用该声明是可选的。

规范定义的Audience(aud)声明是通用的,并且是应用程序特定的。它的预期用途是标识令牌的预期接收者。接收者的含义是应用程序特定的。受众值可以是字符串列表,或如果只有一个aud声明,则可以是单个字符串。创建令牌的人不强制执行对aud的正确验证,确定是否应使用令牌的责任在于接收方。

无论值是什么,当接收方验证 JWT 并希望验证该令牌旨在用于其目的时,它必须确定aud中的哪个值标识自己,仅当接收方声明的 ID 存在于 aud 声明中时,该令牌才应验证。这不管是 URL 还是其他应用程序特定字符串都可以。例如,如果我的系统决定使用字符串 "api3.app.com" 在 aud 中标识自己,则只有当 aud 声明包含 "api3.app.com" 时,它才应接受 JWT 到达。 当然,接收方可能选择忽略 aud,因此只有在接收方希望积极验证该令牌是否专门为其创建时,此限制才有用。 基于规范,我理解 aud 声明对于创建仅针对特定目的有效的 JWT 很有用。对于某个系统,这可能意味着您希望令牌对某些功能有效,而对其他功能无效。您可以发出仅限于某个“受众”的令牌,同时仍使用相同的密钥和验证算法。 由于在典型情况下 JWT 是由受信任的服务生成并由其他受信任的系统使用(这些系统不想使用无效的令牌),这些系统只需要协调它们将要使用的值即可。 当然,aud 是完全可选的,如果您的用例不需要它,则可以忽略它。如果您不想将令牌限制为特定观众使用,或者您的系统实际上都不会验证 aud 令牌,则 aud 就没有用处。 例如:访问令牌与刷新令牌的示例 我可以想到一个牵强(但简单)的例子是,也许我们希望为访问和刷新令牌使用 JWT 而无需实现单独的加密密钥和算法,但只是要确保访问令牌不会验证为刷新令牌,反之亦然。通过使用 "aud",我们可以在创建这些令牌时指定刷新令牌的“refresh”声明和访问令牌的“access”声明。当从刷新令牌请求新的访问令牌时,我们需要验证该刷新令牌是真正的刷新令牌。如上所述的“aud”验证将告诉我们是否通过在“aud”中专门查找“refresh”的声明来查看令牌是否实际上是有效的刷新令牌。
OAuth客户端ID与JWT“aud”声明之间没有任何直接关联。从OAuth的角度来看,令牌是不透明的对象。接受这些令牌的应用程序负责解析和验证这些令牌的含义。我认为在JWT“aud”声明中指定OAuth客户端ID没有多少价值。

4
我不太理解整个“必须标识自身”的部分。RFC7519充满了像这样的未经解释的细节,以及对其他认证系统的模糊暗示,这可能是标准申报字段的正确解释所在。坦白说,虽然RFC可能很有用,但它不应该以这种状态离开草案阶段。 - Chuck Adams
1
@ChuckAdams 我编辑了一下以澄清我的想法。我同意RFC非常模糊,特别是在“标准声明”和何时/如何使用它们方面。 - Kekoa
3
目前我们正在讨论如何使用aud字段,我同意它的含义是包含接收者(验证并接受令牌的人),而不是客户端ID(请求代表用户操作令牌的人)。 - hardysim
以下内容是完全错误的,与RFC 7519相违背:“当然,接收方可以选择忽略aud,因此只有在接收方希望积极验证token是否专门为其创建时才有用。”RFC 7519中的句子:“如果处理声明的主体在aud声明中没有使用值标识自己,则必须拒绝JWT。”意味着如果存在受众声明,您必须使用它来检查是否与其值之一匹配。 - Maarten Derickx
它是可选的,这意味着发行人可以选择不包括它,但是当它存在时,接收者不能将其丢弃。 - Maarten Derickx

19

如果你搜索OpenID Connect (OIDC):

我知道这标记为oauth 2.0而不是OIDC,但是经常会将两个标准混淆,因为两种标准都可以使用JWT和aud声明。其中一个(OIDC)基本上是另一个(OAUTH 2.0)的扩展。(我自己也在寻找OIDC时偶然发现了这个问题。)

OAuth 2.0访问令牌##

对于OAuth 2.0访问令牌,现有的答案已经很好地涵盖了它。此外,以下是OAuth 2.0 Framework (RFC 6749)中的一个相关部分:

对于使用隐式流的公共客户端,本规范没有提供任何方法让客户端确定访问令牌发放给哪个客户端。
...
将资源所有者身份验证到客户端超出了本规范的范围。任何使用授权过程作为委派用户身份验证到客户端的形式(例如,第三方登录服务)的规范,如果没有额外的安全机制来使客户端能够确定是否为其使用发放了访问令牌(例如,针对受众-限制访问令牌),则不能使用隐式流。

OIDC ID令牌##

OIDC除了Access tokens之外还有ID Tokens。OIDC规范在ID Tokens中使用aud声明时是明确的。(openid-connect-core-1.0

aud
必选项。该ID Token的目标受众。 它必须包含Relying Party的OAuth 2.0客户端ID作为受众值。 它也可以包含其他受众的标识符。一般情况下,aud值是区分大小写的字符串数组。当只有一个受众时,aud值可以是单个区分大小写字符串。

此外,OIDC规定了在aud具有多个值时与其一起使用的azp声明。

azp
可选项。发出ID Token的授权方- 接收ID Token的一方。如果存在,则必须包含此方的OAuth 2.0客户端ID。仅当ID Token具有单个受众且该受众不同于授权方时才需要此声明。即使授权方与唯一受众相同,也可以包括它。azp值是包含StringOrURI值的区分大小写字符串。


2
只需要注意一件事:Oauth2不强制使用JWT。 - zoran

7

虽然这篇文章是老的,但我认为问题即使今天仍然存在。

我怀疑 aud 应该指的是资源服务器,而 client_id 应该指的是身份验证服务器识别的客户端应用程序之一

是的,aud 应该指向使用令牌的一方。而 client_id 指的是获取令牌的一方。

在我的当前情况下,我的资源服务器也是我的 Web 应用程序客户端。

在原帖作者的情况下,Web 应用程序和资源服务器都属于同一个实体。这意味着客户端和受众是相同的。但也有可能出现这种情况不成立的情况。

想象一下一个基于 SPA 的 OAuth 受保护资源的场景。在这种情况下,SPA 是客户端。受保护的资源是访问令牌的受众。

这第二个场景很有趣。RFC8707 "OAuth 2.0 资源指示器" 解释了您可以在授权请求中使用 resource 参数定义预期受众的位置。因此,生成的令牌将受到限制,并只能用于指定的受众。Azure OIDC 采用了类似的方法,允许资源注册,并允许认证请求包含资源参数以定义访问令牌的预期受众。这种机制允许 OAuth 适应具有客户端和使用令牌(受众)方分离的实体。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接