假设我们有一些我们想要公开其资源的RESTful API.最终用户将通过客户端应用程序(如移动应用程序和在Web浏览器上运行的基于Javascript的客户端)使用此API.
使用OAuth 2.0,这个RESTful API将位于资源服务器上,我们将有一个授权服务器,客户端应用程序在其上注册.然后,用户将在授权服务器上注册,并且能够授予这些应用程序代表他们访问资源的权限.
因此,当用户访问一个客户端应用程序时,他将被重定向到授权服务器并被提示授予所述客户端应用程序的权限.之后,发出访问令牌,客户端能够向资源服务器发出请求.
所有这些对我来说都很清楚.只有一个缺失的部分:每个资源的保护可能取决于用户.更确切地说,它可能是依赖于声明的.我的意思是我们可以有以下情况:
只有声明为"ExampleClaim"且值为123的用户才能访问资源http://resourceserver.com/api/first-resource.
只有声明为"AnotherClaim"且值为123的用户才能访问资源http://resourceserver.com/api/second-resource.
任何用户都应该可以访问资源http://resourceserver.com/api/third-resource.
当我第一次听说OAuth正在处理ASP.NET WebAPI时,我通过以下方式解决了这个问题:当请求与Authorization: Bearer [token]
头一起发送时,在服务器端设置了线程主体,我认为这意味着用户已经过身份验证使用API.所以我使用[Authorize]
属性来验证用户是否可以访问资源.
在更深入地研究了OAuth之后,我看到这是对协议的一种可怕的滥用.据我所知,OAuth授权应用程序而不是用户.正如我所知,当使用Authorization标头发出请求时,访问令牌不应包含有关用户的信息,而是包含允许发出请求的应用程序的信息.
考虑到这一点,发送带有请求的Authorization标头不会识别用户,也不会说用户是否可以访问所述资源.
在这种情况下,如何执行此类授权?我的意思是,不是授权执行请求的客户端应用程序,而是根据其声明访问资源的用户的授权?我相信这是OpenID Connect及其ID令牌的用武之地,但我不确定.如何管理这个?
访问令牌不包含用户的声明,但它包含已授予客户端应用程序权限的用户的主题."主题"是一个技术术语,它表示唯一标识符.简单地说,"subject"是数据库中的用户ID.
在受保护的资源端点,您将执行以下操作:
从请求中提取访问令牌.(RFC 6750)
从授权服务器获取有关访问令牌的详细信息.(RFC 7662)
验证访问令牌.验证包括(a)访问令牌是否已过期,以及(b)访问令牌是否涵盖受保护资源端点所需的范围(权限).
上面的步骤从1到3是对客户端应用程序的访问控制.OAuth 2.0(RFC 6749)就是为此而做的.有关这些步骤的详细信息,请参阅Authlete(由我)提供的" 受保护的资源 " .
完成上述步骤后,您将执行以下操作:
从访问令牌中提取主题.同样,"主题"是用户的唯一标识符.
从数据库中检索用户的声明.
根据需要验证声明.
上述步骤4到6是对用户的访问控制.OAuth 2.0不适用于此.
OpenID Connect的主要目的是以可验证的方式获取ID令牌.您可以通过验证附加到ID令牌的签名来确认权利方已发出ID令牌.有关签名的详细信息,请参阅JSON Web签名(JWS)(RFC 7515).
ID令牌本身不是保护Web API的技术.但是,如果您at_hash
正确使用ID令牌中的声明,则可以将其用于此目的(请参阅OpenID Connect Core 1.0中的 " 3.1.3.6.ID令牌 " ).但是,在受保护的资源端点上,直接从数据库获取声明比解析ID令牌要容易得多.
在您的用例中,您不需要ID令牌.这是因为访问令牌已包含有关用户主题的信息.在正常情况下,信息等同sub
于ID令牌中的声明值.
因此,您不需要ID令牌来获取用户的主题.请参阅步骤4的说明,您可以找到"从访问令牌中提取主题".
那么从访问令牌中提取主题是否有任何问题并验证声明?或者这是正确的做事方式?
没有任何错误.例如,假设您定义了一个Web API https://api.example.com/profile
,它返回用户的配置文件信息.在正常情况下,此类API将接受访问令牌,然后从访问令牌中提取主题以确定要引用的用户.另一方面,如果API没有从访问令牌中提取主题,则必须要求"subject"作为请求参数来确定引用哪个用户(或者需要包含"sub"声明的ID令牌) .即使在这种情况下,API也必须检查请求参数指定的主题和与访问令牌相关联的主题是否相同,否则它将成为安全问题.
提取主题后检查声明也是正常步骤.例如,您可能希望根据用户已支付的计划(免费计划,精简计划,企业计划或其他)限制服务的功能.在这种情况下,您必须参考plan
索赔.当然,只有在从访问令牌中提取主题之后才能检查这样的声明.
因此,(1)从访问令牌中提取主题然后(2)验证用户的声明是受保护资源端点的实现中的正常甚至典型步骤.