放置API密钥的位置:自定义HTTP标头与自定义方案的Authorization标头


17

我正在设计一个通过API密钥使用授权/身份验证的REST API。

我试图找出最合适的位置,然后发现许多人建议使用自定义HTTP标头ProjectName-Api-Key,例如:

ProjectName-Api-Key: abcde

但在Authorization标头上使用自定义方案也是可能的,从思想上来说也是正确的,例如:

Authorization: ApiKey abcde

另一方面,我发现一个考虑,自定义授权方案可能出乎意料,并且不受某些客户端支持,并且无论如何都会导致自定义代码,因此最好使用自定义标头,因为客户对此没有任何期望。

您希望以哪种方式发送API密钥?


在我的指导下,这些项目使用Authorization: Bearer <token>标头,因此从来没有一个问题。令牌是JWT
安迪

1
@DavidPacker据我了解,该Bearer方案专门用于oAuth2。将其与oAuth分开应用听起来是滥用。如果没有oAuth,为什么使用此方案是正确的?顺便说一下,我在为API选择一种授权类型时遇到了麻烦。该API仅可用于一项受信任的服务,因此我调查了oAuth2的客户端凭据流程,在我的案例中,与ApiKey相比没有发现任何好处。
RomanG

@DavidPacker然后,我了解到,如果ApiKey授权ApiKey被重命名并解释为Access Token授予客户端的授权而没有到期时间,则可以将其视为有效的oAuth实现。那是一种哲学方面,如果可以用简单的术语描述我的情况,我决定不带复杂的定义,而是决定将其称为“ ApiKey”。如果您的协议实现了oAuth标准,则可以同意使用Bearer,但事实并非如此,我猜想该方案无法应用。
RomanG

2
您限制自己太多了。无论是否已实现OAuth,API使用者都不会在乎。他们关心的是令牌安全,令牌发行有效并且可以正确进行身份验证。他们建议直接在JWT文档中使用Bearer 。JWT非常适合Bearer模式,我不能推荐更多JWT。它们非常适合REST应用程序,因为您可以在不访问数据库的情况下对用户进行身份验证-除非需要令牌吊销功能。
安迪

1
(开车经过)...请注意,api密钥是通常在已配置的依赖方和验证者之间共享的共享机密 ,而不是传达身份或授权。换句话说,它们仅用于发起安全握手,并不表示认证结果。api密钥传达您的权力,以根据系统的受信任身份验证器来标识自己。使用密钥作为令牌来控制安全资源访问是一件很糟糕的事情
K. Alan Bates

Answers:


12

如果您使用授权,请保持一致

有人会争辩说以下内容是不必要的(不久前我会与他们达成一致),但是如今,如果我们使用Authorization标头,则应该告知令牌的类型,因为 API密钥如今本身并不是自描述的1

为什么我认为这是必要的,为什么我确实认为这很重要?因为如今支持不同的身份验证/授权协议已成为必须。如果我们计划使用Authorization标头用于所有这些协议,则必须使我们的身份验证服务一致。标头中也应包含通信方式,以发送我们发送哪种令牌以及应应用哪种授权协议。

Authorization: Basic xxxx
Authorization: Digest xxxx
Authorization: Bearer xxxx
Authorization: ApiKey-v1 xxxx
Authorization: ApiKey-v2 xxxx

我以前并不关心此事,但是在处理了无法保证更新的应用程序客户端应用程序(主要是手机和传感器)之后,我开始了。我开始对实现安全性的方式更加谨慎,这样我就可以扩展它而不会与客户端打扰,也不会给服务器带来太多麻烦。

顾虑

我实施自己的方案时遇到的问题与所评论的问题相似。

另一方面,我发现一个考虑因素是,自定义授权方案可能出乎意料,并且不受某些客户端的支持,并且仍然会导致自定义代码

客户,说库,框架,反向代理

优点

一项重要的优势是缓存。除非您另外声明,否则共享缓存不会缓存标头(这当然很好)。

那么授权还是自定义标题?

以我的经验,实现我自己的Authorization方案比实现自定义授权标头花了我很多(或更多)的工作,只是我使用自定义标头时有更多的设计自由和对缓存的更多控制。原因是相当愚蠢的,大部分时间我有Cache-control设置为 no-cacheno-store,使我可以使对服务器的调用更具确定性(这对于跟踪和测试很重要),而与网络的拓扑结构无关。


1:关于API密钥,我发现此答案非常清楚


4
的使用X-:被弃用的2012 stackoverflow.com/a/3561399/923720
Darkhogg

1
行动!我不知道 编辑并修复。
Laiv

在问这个问题之前,我想大多数人都将API密钥放在URL中,但是使用HTTPS来隐藏它。很高兴看到一些替代方案。例如,Contentful允许授权或查询pamameter:contentful.com/developers/docs/references/content-delivery-api/...
user949300

1
@ user949300 ...使用加密的共享机密(例如ssl上uri中的api密钥)显然比什么都不安全,但是如果被截获并且不提供关于身份的详细信息,则很容易被欺骗。我从未将api_keys用于机器对机器通信之外的任何其他事情,在该通信中,我匹配受信方之间的共享机密和被授权使用该共享机密的白名单机器身份。机器对机器的连接制成后,操作员会使用其他方式进行身份验证。
K. Alan Bates

@K。艾伦·贝茨(Alan Bates)我的大多数API交互都是针对相对“不重要”的事情,例如地理编码的免费层,天气报告等,其中API密钥更多是用于速率限制,而不是严重的用户机密。因此,对于OP,取决于所需的安全级别。
user949300 '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.