管理API访问令牌的最佳安全实践

译文
安全 应用安全
如今API的使用已非常普遍,而我们对其安全性的管理则显得尤为重要。本文从应用程序集成和开发的角度,与您讨论管理API访问令牌的最佳实践。

【51CTO.com快译】如今,无论是基于Web的应用、还是本地原生的各种程序,都需要通过后端的API来实现资源的访问保护。要想得到API的授权,各种访问请求就必须包含相应的访问令牌或密钥。本文将向API提供者和应用程序开发人员重点介绍,我们在管理访问令牌中的各种最佳安全实践。

[[251397]]

一、安全的第一原则

在我们处置安全性时,首先要考虑的一条原则是:不可相信任何人。如果您是一名API提供者,您不能保证正在调用API的应用程序就是您所预期的那个,您无法确信收到的令牌没有被盗,或者客户端和服务器之间的通信没有被截获。特别是在客户端,您无法确认应用程序没有被反编译过(而且已暴露了内嵌在应用程序之中的密码)。当然,您也无法确定应用程序的存储不会受到跨站脚本式攻击(详见https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)),更无法保证您的用户没有在被欺骗的状态下进行伪造请求的提交(详见https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF))。可见,您必须采取适当的措施,来安全地获取、存储和管理那些调用后端API所需的安全令牌。

另外,您也许会认为:只要不被公开发布出去,自己的API就是安全的。您甚至还可能认为:由于API仅被自己的企业应用程序所用到,它们理所当然是私有的。可殊不知,如果它们可以在某个移动应用中被调用,那么它们就置于了公网之上。也就是说,任何暴露在企业网络外部的API,都应被视为公开的(详见

https://www.42crunch.com/a10-owasp/)。

二、获取令牌的API密钥

在使用API​​时,我们通常有两种选择:一种是将一段静态信息与API调用同时进行传递;另一种是在调用API之前,动态地获取一段信息。这段信息通常被称为访问令牌或API密钥。由于一些历史遗留的问题,BasicAuth(译者注:BasicAuth认证方式是在每次请求API时,仅提供用户的username和password)仍在被某些API所使用着,但实际上,它已经不再是主流的认证解决方案了。

因此,在设计API的安全性方面,您必须谨慎地考虑到API使用者将如何去访问它。而在考虑所采用的安全措施时,您需要全面地分析各种风险因素。显然,我们对于咨询天气数据的API、与银行支付类型的API的保护,会采用截然不同控制措施。

虽然API​​密钥能够被开发人员轻松地实现和使用,但它的安全级别不及于使用访问令牌,通过双因素身份验证,来正确地识别出客户端应用身份的方式。此外,API密钥并不携带任何有关用户的信息,因此它不能被后端级别(backend level)用来决定API使用者可以进行哪些调用操作。再者,除非API提供者主动撤销,否则API密钥永远不会过期。

针对上述缺点,OAuth应运而生,其特点如下:

  • 访问资源的应用程序是已知的(用到了客户端应用程序的信任凭据)。
  • API提供者可以通过定义范围,来限制对某些操作的访问(您可以GET到某个目录条目,但是就算使用的是有效的令牌,您仍然无法PUT新的目录条目)。
  • 令牌具有有限的生命周期。

三、让我们从一些术语开始

OAuth所用到的术语有时会让人感到费解,让我们通过下面的表格,来了解一些与开发有关的重点术语。

四、Opaque与JWT

由于OAuth并不限制使用访问令牌的格式,因此按照OAuth服务器的实现规则,访问令牌既可以是Opaque(通常是一条不带有任何有用信息的长字符串),也可以是一种JSON Web令牌(JWT)。

JWT的优势在于它能够包含各种声明、或是有关用户的信息,而后端服务则可以籍此来进行各种业务逻辑的决策。

五、学习“OAuth舞蹈”

OAuth的授权类型决定了客户端将如何获取令牌。这在我们自己团队内部,常被戏称为“OAuth舞蹈”。因为虽然在OAuth世界中,有着很多种“跳舞形式”,但是有一种您必须记住,那就是:授权代码。虽说在某些情况下,其他授权类型可能也非常实用,但授权代码类型则是包括Web应用、原生应用、和移动应用在内的所有应用程序,获取访问令牌的推荐方法(详见

http://www.pingidentity.com/en/company/blog/posts/2018/securely-using-oidc-authorization-code-flow-public-client-single-page-apps.html)。

特别对于公共客户端和移动应用而言,我们建议采取额外的安全措施,来防止授权代码被盗。此类安全层往往被称为“代码交换证据密钥”(Proof Key for Code Exchange,PKCE)标准。您可以通过链接:https://tools.ietf.org/html/rfc7636,了解更多有关PKCE,以及如何使用它的信息。如果您是API提供者,请确保自己的OAuth服务器能够支持此选项。

同时,您应该特别注意资源所有者的密码授权。虽然它实现起来最为简单,但是由于其核心要求是在客户端与服务器间建立信任关系,因此您可能永远也用不到它。

六、令牌管理的建议

1. 注意OAuth应用的凭据泄漏

您会把应用程序的代码存储在GitHub中吗?您的OAuth应用凭据是否也会存储在那儿,特别是客户端的密钥?可您知道吗?这已经成为了当今信任凭据泄密的头号来源。只要这些凭据被盗,任何人都可以伪装成您的身份,发起中间人攻击。因此,如果您一旦发现凭据可能已被泄露,那就请立即重新生成新的凭据。

此外,请永远不要将客户端的密码放置在分布式代码之中,例如:通过应用软件商店、或客户端JavaScript下载的各类应用里。

2. 不要在应用程序中对令牌进行硬编码

千万不要为了图省事,而简化获取令牌的代码,并将其长时间存储在自己的应用程序之中。

3. 像处置密码一样去处置令牌

由于任何掌握了令牌和API密钥的人都能访问到对应的资源。因此,我们需要像处置各种密码那样,去认真地处理和保存各种令牌。

4. OAuth并非是身份验证协议

OAuth处理的是对资源访问权限的委派,因此它并非是一种身份验证协议(尽管名称很像)。我们可以将令牌看作酒店房间的钥匙。您需要让自己的身份得以验证,方可获得酒店钥匙。但是,一旦您手中已有了钥匙,它就不能再去验证您是谁了。最近发生的一些用户信息泄露事件证明了,API提供者不可单一地将是否持有令牌作为身份验证的依据。

另外,我建议您也参考一下OpenID Connect(OIDC,详见https://www.oauth.com/oauth2-servers/openid-connect/)。不过,它只是一种补充性的规范,而并非是想在OAuth之上实现身份验证的功能。OIDC允许用户与应用程序共享其配置文件里的某些信息,但并不是他们的信任凭据。

5. 注意您在JWT中存储的内容和谁有权限访问

JWT能够以各种声明的形式存储大量的信息,如果这些信息被捕获,攻击者就能够轻松地解析出具体的内容(除非它们被加密了)。因此,如果您想使用JWT向后端服务传递有用的信息,那么您可以采用如下的实现方法:

  • 在客户端和后端之间,仅使用Opaque字符串、或是基本的JWT。
  • 在后端,验证某个请求、并注入一个新的JWT,它的有效负载中可包含一个能够被下游用到的声明。许多API安全网关都能以“开箱即用”的方式提供该功能。

如果想在整个流程中使用相同的令牌,并且让该令牌携带一些敏感的信息,那么请您务必加密该令牌的有效负载。也就是说,请永远不要使用JWT来携带用户的信任凭据,例如:密码!

6. 彻底验证JWT

当您在服务器端收到JWT时,请务必彻底验证其内容。需要特别注意的是:您应该直接拒绝任何不符合预期的签名算法、使用了弱签名算法、和使用了弱非对称/对称密钥进行签名的JWT。此外,您必须验证所有的声明、到期日期、发布者和受用者。

在市面上,有些库和工具可以直接为您执行该操作、有些则需要您事先进行适当的配置、而另一些可能只能做到部分检查。因此,具体该使用哪一种方式,还取决于您所使用到的库。

7. 不要将令牌存储在本地,请使用安全的Cookie

任何在浏览器上的本地存储、和会话存储,都有可能被JavaScript所读取到。可见,用此方式来存储令牌之类的敏感信息是极不安全的。因此,您可以使用安全的Cookie、带httpOnly的标识、以及CSRF等措施,来防止令牌被盗。

8. 始终通过HTTPS和请求正文(Request Body)的方式传输令牌

通过这种方法,您可以限制令牌在传输过程中被捕获,或是被写到代理日志、以及服务器日志之中的风险。您还应该确保只使用TLS的1.2/1.3版本,以及在颁发和验证令牌的各个环境中,使用最安全的密码套件。

9. 使用专用的浏览器视图来请求信息

许多应用程序都用到了嵌入式的用户代理,但是,由于它屏蔽了用户去验证与之通信的网站真伪,因此,我们实际上应当避免使用这样的代理。此外,应用程序应当能够完全掌握用户所输入的凭据。正如那些OAuth原生应用所采用的最佳做法那样,一些API提供者会采取强安全措施,来应对此类问题。

七、结论

访问令牌是如今各种应用程序的实现基础,因此我们在处置的时候一定要倍加小心。如果您是一名后端开发者,您必须确保提供适当的授权类型,以获取访问令牌;同时还应该支持移动应用的PKCE;以及对JWT进行全面验证。而如果您是一位前端开发者,则必须能够管控JWT的存储、并保护应用的各种信任凭据。

参考

  • PKCE(https://tools.ietf.org/html/rfc7636)
  • JWT的验证实践(https://tools.ietf.org/html/draft-ietf-oauth-jwt-bcp-03)
  • 原生应用程序的最佳实践OAuth(https://tls.mbed.org/)

原文标题:Security Best Practices for Managing API Access Tokens,作者:Isabelle Mauny

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

责任编辑:赵宁宁 来源: 51CTO
相关推荐

2023-12-05 07:51:54

2023-04-14 12:23:15

2016-12-27 08:49:55

API设计策略

2013-06-13 09:21:31

RESTful APIRESTfulAPI

2023-05-24 12:33:35

2018-04-04 04:26:09

2024-01-05 00:33:23

2023-11-07 07:08:57

2017-03-13 14:09:19

RESTful API实践

2014-06-09 15:50:08

2011-01-18 09:26:00

2009-12-31 10:16:49

2013-09-17 11:28:48

2009-07-28 09:54:23

.NET内存管理

2013-06-09 10:38:54

IT运维管理运维管理ITIL管理

2022-07-07 08:00:00

VDI虚拟化虚拟桌面

2014-06-27 13:32:07

GartnerAWS安全亚马逊AWS

2018-08-28 07:30:50

云安全云服务多云

2009-08-20 09:41:36

2013-12-26 09:11:39

点赞
收藏

51CTO技术栈公众号