引言:如今API的使用已非常普遍,而我们对其安全性的管理则显得尤为重要。本文从应用程序集成和开发的角度,与您讨论管理API访问令牌的最佳实践。
如今,无论是基于Web的应用、还是本地原生的各种程序,都需要通过后端的API来实现资源的访问保护。要想得到API的授权,各种访问请求就必须包含相应的访问令牌或密钥。本文将向API提供者和应用程序开发人员重点介绍,我们在管理访问令牌中的各种最佳安全实践。安全的第一原则在我们处置安全性时,首先要考虑一条原则是:不可相信任何人。如果您是一名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所用到的术语有时会让人感到费解,让我们通过下面的表格,来了解一些与开发有关的重点术语。
实用名称
| OAuth术语
| 描述
|
应用
| 客户端
| 客户端是一个代表用户访问资源的应用程序。
|
Web服务器应用
| 机密性客户端
| 应用程序运行在服务器端,能够安全地存储应用程序的密钥。
|
单页面应用/基于浏览器的应用/移动应用
| 公共客户端
| 是一个应用程序,它要么完全运行在客户端、要么是在无法安全地存储应用密钥的设备上。
|
API
| 资源服务器
| 访问那些属于用户的资源(例如银行账户)的一种方式。
|
OAuth服务器
| 授权服务器
| 负责处理OAuth令牌并管理请求(授权访问、发放令牌、撤销令牌)。
|
用户
| 资源所有者
| 能够授权应用程序访问资源的人。
|
访问令牌
| 持票人令牌
| 能够授权应用程序访问API。
|
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服务器能够支持此选项。同时,您应该特别注意资源所有者的密码授权。虽然它实现起来最为简单,但是由于其核心要求是在客户端与服务器间建立信任关系,因此您可能永远也用不到它。令牌管理的建议注意OAuth应用的凭据泄漏您会把应用程序的代码存储在GitHub中吗?您的OAuth应用凭据是否也会存储在那儿,特别是客户端的密钥?可您知道吗?这已经成为了当今信任凭据泄密的头号来源。只要这些凭据被盗,任何人都可以伪装成您的身份,发起中间人攻击。因此,如果您一旦发现凭据可能已被泄露,那就请立即重新生成新的凭据。此外,请永远不要将客户端的密码放置在分布式代码之中,例如:通过应用软件商店、或客户端JavaScript下载的各类应用里。不要在应用程序中对令牌进行硬编码千万不要为了图省事,而简化获取令牌的代码,并将其长时间存储在自己的应用程序之中。