英文:
How to additionally secure a REST service that is already using an OAuth 2.0 access token?
问题
- 一个聚合器服务,向外部提供服务。它由用户OAuth 2.0访问令牌进行安全保护。这个聚合器会调用内部服务。
- 内部服务位于网络层级上,不向外界开放。同样也由相同的用户OAuth 2.0访问令牌进行安全保护。访问令牌从聚合器传递到内部服务。
现在假设内部服务被意外地暴露给外界。理论上,用户可能会对内部服务进行不应允许的更改。
是否有一种方式可以额外保护内部服务,以便即使它被意外地暴露给用户,他们也无法访问它?
是否可以或者明智地同时使用机器对机器(M2M)令牌和用户令牌来保护内部服务?
英文:
I've got the following REST services:
- An Aggregator service that is exposed to the outside world. It is secured by a user OAuth 2.0 access token. This Aggregator calls the Internal service.
- The Internal service is on a network-level not exposed to the outside world. It is also secured by the same user OAuth 2.0 access token. The access token is passed from the Aggregator to the Internal service.
Now let's say the Internal service is by accident exposed to the outside world. In theory, users could then make changes to the Internal service that should not be allowed.
Is there a way to additionally secure the Internal service, so that users can't access it even though it would be exposed to them by accident?
Would it be possible or wise to use both a Machine to Machine (M2M) token and a user token to secure the Internal service?
答案1
得分: 1
最正确的OAuth设计方式是使用范围和声明。这样做有效地允许访问令牌和用户身份在微服务之间流动,具有正确的保护措施,而无安全顾虑。最好通过一个例子来解释。
场景
考虑一个在线销售业务场景。客户与订单服务交互,订单服务调用了结算服务。客户不直接调用结算服务,但在那里执行了用户发起的操作。
访问令牌流动
范围的设计并不由OAuth标准定义。通常由架构师为端到端的业务流程设计。下面是一个示例,其中每个API在每个请求上接收并验证JWT访问令牌。请注意,有时客户端会发送不同的凭证,例如cookie或引用令牌,但这些会被转换为JWT访问令牌,然后传递给API。
用户身份从订单API流向结算API。它保持可验证和可审计,因为它使用JWT格式。两个API以零信任方式在每个请求上验证JWT。
API还会检查所需的范围。在这个示例中,我让每个微服务的范围相同,因为它们都涵盖相同的业务领域。结算API可能只允许在创建发票操作时使用此范围。如果访问令牌被发送到任何其他结算端点,或者发送到范围不足的任何其他API,它将立即被拒绝,并返回403禁止响应。要创建发票,结算API可能会添加其他限制,例如对负载中的订单ID进行检查。
在JWT验证后,API相信令牌中的声明并将其用于业务授权。这将根据用户身份、角色和其他值限制用户可以做什么。因此,如果用户能够使用浏览器工具提取其API凭证,并使用诸如Postman之类的工具进行重播,他们应该获得与UI会话中获得的完全相同的对API的访问权限。
高权限操作
API还将被其他用户和客户端使用,他们可能需要调用高权限操作。考虑下一个可能调用相同API的几个员工应用程序,这些应用程序也可能会暴露给互联网。这些应用程序可能允许更高的权限,并且可能需要多因素身份验证。
在这里,我也使用了分层范围,例如 sales:payments
,这是一种设计访问API端点的可能技术之一。然而,范围仍然保持在高层级,并且只管理入口级别的安全性。
其他选项
还有更高级的选项来流动令牌。例如,OAuth令牌交换 可以在调用上游API之前用于获取同一用户的不同令牌。通常情况下,这用于为同一用户获取一个具有减少范围的令牌。
也可以为上游API获取具有完全不同范围的令牌,但在某些情况下这样做可能会削弱安全性。执行此操作的解决方案通常使用客户端凭据流程,以获取具有诸如 billing
等范围的令牌,然后将用户ID传递在不可验证的标头或URL路径段中。因此,该令牌可能会访问过多用户的数据,并且具有这样令牌的恶意方可能会更改用户ID。
单独的基础设施解决方案,例如要求对结算API使用相互TLS,也存在一些问题。它们可能会阻止真正的客户对该API的访问。这可能与业务所有者的意图相悖。在上面的示例中,它将阻止财务应用程序能够调用结算API。
总结
如果需要的话,基础设施解决方案可能是最好的短期战术解决方案。然而,作为未来的方向,应该努力利用OAuth提供的零信任要素,通过在最佳方式中使用范围和声明。
英文:
The most correct OAuth way to design this is to use scopes and claims. Doing this effectively allows access tokens and the user identity to flow between microservices, with the right protections and without security concerns. It is best explained by an example.
SCENARIO
Consider an online sales business scenario. A client interacts with an orders service, which calls a billing service. The client does not call the billing service, yet user initiated operations are performed there.
ACCESS TOKEN FLOWS
How scopes are designed is not defined by the OAuth standard. Usually they are designed by architects, for end-to-end business flows. An example is shown here, where each API receives and verifies a JWT access token on every request. Note that sometimes the client sends a different credential, eg a cookie or reference token, but these get translated to JWT access tokens, which are delivered to APIs.
The user identity flows from the Orders API to the Billing API. It remains verifiable and auditable, since it uses the JWT format. Both APIs validate the JWT on every request, in a zero trust manner.
The APIs also check for required scopes. In this example I have made the scope the same for each microservice, since they both cover the same business area. The Billing API may only allow this scope for the Create Invoice operation. If the access token is sent to any other Billing endpoints, or any other API where the scope is insufficient, it is rejected immediately with a 403 forbidden response. To create an invoice, the Billing API might add other restrictions, eg related to checks on an order ID in the payload.
After JWT verification the APIs trust the claims in the token and use them for business authorization. This would lock down what the user can do based on user identity, roles and other values. So if the user was able to use browser tools to extract their API credential and replay it using a tool such as Postman, they should get precisely the same access to APIs that they get in their UI session.
HIGHER PRIVILEGE OPERATIONS
The APIs will also be used by other users and clients, who may need to call higher privilege operations. Consider next a couple of employee apps that call the same APIs, and which might also be exposed to the internet. These might allow higher privileges and require multi-factor authentication:
Here, I am also using hierarchical scopes, such as sales:payments
, which is one possible technique to design access to API endpoints. Scopes remain high level though, and only manage entry level security.
OTHER OPTIONS
There are more advanced options for flowing tokens. For example, OAuth token exchange can be used to get a different token for the same user before calling an upstream API. Most commonly this is used to get another token for the same user with a reduced scope.
It is possible to get a token with a completely different scope for an upstream API, but doing so may weaken security in some cases. Solutions that do this often use the client credentials flow, to get a token with a scope such as billing
, then pass the user ID in an unverifiable header or URL path segment. Thus the token may have access to data for too many users, and a malicious party with such a token might change the user ID.
Infrastructure solutions alone, such as requiring mutual TLS for the Billing API, also have some problems. They may prevent access to that API by genuine clients. This can work against what the business owners want. In the above example, it would prevent the finance app from being able to call the Billing API.
SUMMARY
An infrastructure solution might be the best short term tactical solution, if you need one. As a future direction though, aim to use the zero-trust ingredients that OAuth provides, by using scopes and claims in the best ways.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论