如何验证OAuth 2.0访问令牌用于资源服务器?

208
当客户端通过OAuth 2.0访问令牌请求受保护的资源时,资源服务器如何验证该令牌? OAuth 2.0刷新令牌协议是如何运作的?

服务器应该能够验证它之前发行的令牌...通常这将是一个数据库查找或加密(自签名令牌)。 - Thilo
我明白了。那么如果资源所有者WS和客户端WS在不同的设备上呢? - Ack
6
你的意思是认证服务和资源服务吗?(客户端/消费者将始终在不同的设备上,并且无法自行验证令牌)如果是这种情况,您可以使用“昂贵”的刷新令牌进行检查(只有授权服务器可以执行此操作),但其寿命长;而访问令牌则会经常过期并可离线检查。 - Thilo
1
http://blog.facilelogin.com/2016/03/adding-oauth-20-token-introspection.html - Prabath Siriwardena
6个回答

141

Google方式

Google OAuth2令牌验证

请求:

https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=1/fFBGRNJru1FQd44AzqT3Zg

回复:

{
  "audience":"8819981768.apps.googleusercontent.com",
  "user_id":"123456789",
  "scope":"https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
  "expires_in":436
} 

微软方式

Microsoft - 检查授权的 OAuth2

Github 方式

Github - 检查授权的 OAuth2

请求:

GET /applications/:client_id/tokens/:access_token

回复:

{
  "id": 1,
  "url": "https://api.github.com/authorizations/1",
  "scopes": [
    "public_repo"
  ],
  "token": "abc123",
  "app": {
    "url": "http://my-github-app.com",
    "name": "my github app",
    "client_id": "abcde12345fghij67890"
  },
  "note": "optional note",
  "note_url": "http://optional/note/url",
  "updated_at": "2011-09-06T20:39:23Z",
  "created_at": "2011-09-06T17:26:27Z",
  "user": {
    "login": "octocat",
    "id": 1,
    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
    "gravatar_id": "somehexcode",
    "url": "https://api.github.com/users/octocat"
  }
}

亚马逊方式

使用亚马逊登录 - 开发者指南(2015年12月,第21页)

请求:

https://api.amazon.com/auth/O2/tokeninfo?access_token=Atza|IQEBLjAsAhRmHjNgHpi0U-Dme37rR6CuUpSR...

响应:

HTTP/l.l 200 OK
Date: Fri, 3l May 20l3 23:22:l0 GMT 
x-amzn-RequestId: eb5be423-ca48-lle2-84ad-5775f45l4b09 
Content-Type: application/json 
Content-Length: 247 

{ 
  "iss":"https://www.amazon.com", 
  "user_id": "amznl.account.K2LI23KL2LK2", 
  "aud": "amznl.oa2-client.ASFWDFBRN", 
  "app_id": "amznl.application.436457DFHDH", 
  "exp": 3597, 
  "iat": l3ll280970
}

8
它完全没有解释服务器端如何通过令牌识别分配的用户ID。 - user2284570
62
我不明白所有的点赞。这似乎并没有回答问题。 - Duncan Jones
3
有人知道Azure Active Directory是否有类似的终端点来检查已发行的令牌是否有效吗? - user180940
3
换句话说,自己动手做。 - Johann
谷歌似乎已经大幅改变了oauth2令牌的管理方式,因此您的URL不再起作用。请问您能否更新一下这个答案? - deltree
在答案的微软部分提供的链接实际上并没有解释任何内容。那只是一个指向他们的JWT验证服务的链接。 - undefined

119

更新于2015年11月: 根据下面的Hans Z.所述 - 这现在确实被定义为RFC 7662的一部分。

原始回答: OAuth 2.0规范(RFC 6749)没有清晰地定义资源服务器(RS)和授权服务器(AS)之间的访问令牌(AT)验证交互。这实际上取决于AS的令牌格式/策略 - 有些令牌是自包含的(例如像JSON Web Tokens),而其他令牌可能类似于会话cookie,只是引用存储在AS后台的信息。

OAuth工作组已经进行了一些讨论,以创建RS与AS进行AT验证通信的标准方式。我的公司(Ping Identity)已经为我们的商业OAuth AS(PingFederate)提出了一个方法:https://support.pingidentity.com/s/document-item?bundleId=pingfederate-93&topicId=lzn1564003025072.html#lzn1564003025072__section_N10578_N1002A_N10001。这使用REST的交互方式,非常适合OAuth 2.0。


Scott T,有没有办法看到一个在Ping Federate中利用该功能的代码示例? - JavaHead
2
@JavaHead,我们的开发者网站上还涵盖了一些协议细节,您可以在此处查看:https://developer.pingidentity.com/en/resources/oauth-2-0-developers-guide.html#validate_token。<br/><br/>此外,PingFederate OAuth Playground是一组JSPs,可作为源代码引用以验证令牌。它(以及其他开源库和示例)可以从此处下载:https://developer.pingidentity.com/en/code.html。 - Scott T.
Scott,我正在寻找一个示例,演示使用本地资源服务器保护的Rest API的客户端凭据授权和PingFederate作为认证服务器。然后,本地资源服务器将调用验证端点。你有类似的经验吗? - JavaHead
@JavaHead 这是你应该能够参考 PingFederate OAuth Playground 的内容。它展示了客户端凭据授权类型和资源服务器验证访问令牌的过程。 - Scott T.
对于JWT访问令牌,我认为通常情况下您不希望针对RS的每个传入请求都打开AS内省端点。这种情况下,令牌签名和范围的RS检查是否足够?或者,RS可以缓存来自AS的内省响应一段时间吗? - Gary
1
@Gary 你说得没错,但最终取决于实现和AS的功能。AS可能仍然有一些能力来撤销访问令牌,在这种情况下,您可能需要回调以确保已检查。到期和签名检查并不能告诉您应该将AT视为仍然有效。 - Scott T.

65

@Scott T.的回答有更新:关于令牌验证的资源服务器和授权服务器之间的接口已在2015年10月的IETF RFC 7662中进行了标准化,详情请见:https://www.rfc-editor.org/rfc/rfc7662。一个样本验证调用看起来像这样:

POST /introspect HTTP/1.1
Host: server.example.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer 23410913-abewfq.123483

token=2YotnFZFEjr1zCsicMWpAA

和一个示例响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "active": true,
  "client_id": "l238j323ds-23ij4",
  "username": "jdoe",
  "scope": "read write dolphin",
  "sub": "Z5O3upPC88QrAjx00dis",
  "aud": "https://protected.example.net/resource",
  "iss": "https://server.example.com/",
  "exp": 1419356238,
  "iat": 1419350238,
  "extension_field": "twenty-seven"
}

当然,厂商和产品的采用需要逐步实现。


如果使用OpenId Connect,我们是否应该优先选择使用id令牌来验证访问令牌的方式:http://openid.net/specs/openid-connect-core-1_0.html#ImplicitTokenValidation - adnan kamili
1
@Renan:为了与授权请求中请求范围的方式保持一致,需要使用一个 scope 查询参数,其值包含以空格分隔的范围列表。 - Hans Z.
6
请不要在某个事物尚未被管理机构正式接受时使用“标准化”的词语。截至2018年2月,IETF RFC 7662明确指出它是一个“提案”。 - Johann
6
@adnankamili,"proposal"这个词其实并不存在。当一个文档成为RFC时,它已经是一个“拟议标准”,具有重要的背景意义。OAuth 2.0本身仍然是一个“拟议标准”,所以我不确定您想表达什么意思。 - Pace
如果OAuth被认为是一个“三个步骤”的验证过程,那么这个introspect调用是否可以被视为第三个步骤呢?我将“第三个步骤”错误地归因于客户端调用授权服务器来交换授权代码以获取访问令牌。 - eel ghEEz
相关问题 https://dev59.com/hXIOtIcB2Jgan1znKYvx - ses

26

OAuth 2.0规范没有定义这一部分,但是有几个选项:

  1. 当资源服务器在Authz头中接收到令牌时,它会调用Authz服务器上的验证/内省API来验证令牌。在这里,Authz服务器可以使用数据库存储或验证签名和某些属性来验证它。作为响应的一部分,它解码令牌并发送令牌的实际数据以及剩余的过期时间。

  2. Authz服务器可以使用私钥对令牌进行加密/签名,然后将公钥/证书提供给资源服务器。当资源服务器获取到令牌时,它要么解密/验证签名以验证令牌,取出内容并处理令牌。然后它可以提供访问权限或拒绝访问。


11

2021年更新答案

通常不建议自己编写OAuth 2 / OIDC实现的任何部分,特别是现在令牌内省已经成为标准的一部分。就像尝试自己编写加密库一样,对于如此复杂的规范来说,犯下关键错误太容易了。

这里列出了其他语言中推荐的实现OAuth 2的库。这里又有一个OpenID基金会认证的库列表;其中许多库也实现了OAuth 2。

如果你使用IdentityServer库(版本2.2及以上)且在.NET中,则内省端点可以实现此目的。它作为发现文档(同样标准)的一部分发布,是资源服务器可以验证访问令牌的端点。

如果你已经走到这一步,仍然真的想要自己编写,请参考更大的库是如何做到的


内省端点需要客户端凭据(clientID和secret)才能返回响应。在无法保留秘密值的应用程序(SPA,本机应用程序)中如何使用它? - umat
introspect客户端用于API/资源服务器确定由客户端(SPA、本地应用程序等)传递给它的令牌是否被视为有效。只有在授权服务器和API/资源服务器是两个不同的实体时才真正需要它们(它们通常是相同的)。我无法想象客户端需要使用内省的情况。作为替代方案,API/资源服务器可以始终简单地请求公共令牌签名证书并执行自己的验证。我相信该请求可以在没有身份验证的情况下进行。 - J.D. Mallen

9

OAuth v2 规范指出:

访问令牌属性和访问受保护资源所使用的方法超出了该规范的范围,并由相关规范定义。

我的授权服务器有一个 Web 服务 (SOAP) 端点,允许资源服务器知道访问令牌是否有效。


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