2015-04-16 125 views
23

我有一个关于如何构建使用访问令牌和API密钥的REST API的问题。构建API密钥和访问令牌

我有一个需要验证的API。我想启用两个用例:

  1. 使用的OAuth2(密码补助金)的用户登录到界面,并被授予临时访问令牌。该令牌用于认证用户。因此,使用API​​的UI可以获取数据并显示它。

  2. 我也希望用户有一个API密钥来执行相同的调用,但在其应用程序。显然,与访问令牌相反,我希望API密钥长期存在。此外,与绑定到给定用户的访问令牌相反(如果我们引入团队机制,每个用户将拥有不同的访问令牌,虽然他们访问相同的资源),但API密钥应该对项目是唯一的。

虽然相似,但我不确定我应该如何构造它。我认为,在内部,API密钥和访问令牌应该存储在同一个表中,但API密钥没有到期时间。我对吗?

我不确定的一件事还是客户端的概念。看来在规范中,客户端更像是一个外部应用程序。但是我可以在这里实际使用这个概念吗?例如,每个“项目”实际上是一个不同的客户端(虽然这里的客户端是同一个应用程序,而不是由第三方开发者创建的应用程序)。

因此,如果用户A在系统上创建一个帐户,则客户端A将自动创建一个访问令牌,并与一个长期访问令牌(又名API密钥)绑定到客户端A.例如,这可以用来直接在他的代码上执行API调用。

然后,如果用户A登录到仪表板,则会创建一个临时访问令牌,但此时没有应用程序,但与用户绑定,寿命短。

这听起来理智?有没有人已经实现了这样的事情?

谢谢!

+1

API密钥和访问令牌是不同的概念,它们分别进行建模,并将它们分开存储。 –

+0

是的,但你如何处理我想以同质方式访问API的事实?我不想有不同的方式来使用API​​。无论是我的Web应用程序使用临时令牌还是使用API​​密钥直接从其Web服务器使用API​​的客户端使用它。 –

回答

14

我想你不应该把“API密钥”作为访问令牌的替代品。

您将不得不使用访问令牌来承担请求之间的身份验证,因此您实际上使用“API密钥”建模的内容不是替代通常的承载令牌,而是提供了不同的客户端其他授权类型来请求令牌。

我个人实施流程如下:

  1. 用户与普通客户端密码拨款类型,为每个用户(即您的“网络应用”的客户端,这是公开的,即认证它没有client_secret)。
  2. 用户可以创建自己的客户端。根据OAuth2规范,这些规范不公开,因此它们将包含client_idclient_secret。这些就是你所说的“API密钥”。
  3. 用户随后可以通过客户端以任何您希望支持的授权类型(例如直接客户端凭证,授权代码,隐式,第三方等)请求访问令牌。您将不得不对有关如何处理客户端证书的正确安全做法强调一点。

很显然,你将必须实现以这样的方式,客户可以属于特定的用户您的OAuth2服务器,并有不同的接受补助的类型(例如,你可能不希望允许与用户客户端的密码赠款的使用,而您可能想要禁止任何授权类型,而不是您的Web应用程序客户端的授权类型)。

然后,您将能够在每个客户端或每个授权类型的基础上定义令牌TTL(或缺乏)(例如,通过密码授权请求的访问令牌,只能由Web应用程序客户端使用,将具有短TTL,而授权码授予将提供长寿命令牌)。
但我建议不要完全缺乏TTL,而应使用refresh_token授予类型来更新过期的访问令牌。此外,您可能必须定义某种类型的授权系统(ACL,RBAC,无论),以定义哪个客户端可以执行什么操作。这意味着每个访问令牌都应该包含对创建客户端的引用。

所以,概括起来讲,这里的关系:

用户客户
客户端有一个用户
客户端有很多令牌
令牌有一个客户端
令牌有一个用户

YMMV双向。

你应该能够实现我与任何特定平台的最常见的OAuth2服务器实施方案所描述的一切。

TL; DR:“API密钥”实际上是OAuth2 客户端

+0

谢谢斯特凡诺;)。听起来很不错,很合理,虽然我不太喜欢用户需要同时通过client_secret和client_id(这使事情变得更加复杂)的事实。我试图通过分析请求来理解Stripe API的工作原理,看起来他们使用基本验证和生成的API密钥(他们应该生成)以及使用访问令牌(他们的Web应用)的载体。 –

+0

那么,您只需使用一次客户端凭证即可获取访问令牌,而使用基本身份验证时,则可以使用每个请求发送实际凭据。 这更为复杂,确实如此,但如果做得对,它也更安全(因为它与整个OAuth2 vs Basic比较是一样的)。 –

1

我写了一篇关于如何使用RESTful应用程序的访问令牌的文章:https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/。也许这可以提供一些提示。

要回答你的问题,我认为我们需要有一些同质的东西。我的意思是你所有的认证机制应该基于访问令牌。您的API密钥将允许您获取实际用于身份验证的访问令牌。

据我了解,你有两种应用程序的用户:使用Web UI

  • 最终用户(通过OAuth2和密码登陆)
  • 应用程序(使用API​​密钥登录)

所以我会实现这两种用户,并使他们获得访问令牌的能力。访问令牌将用于访问RESTful服务。

另外,我认为这个答案可以给你一些其他的提示:Securing my REST API with OAuth while still allowing authentication via third party OAuth providers (using DotNetOpenAuth)

希望它回答你的问题。 Thierry

2

谢谢您的回答。

我实际上对OAuth2本身非常有经验,我的问题更多地针对API密钥。我喜欢交换访问令牌的API密钥的想法,但我认为这是行不通的。 API密钥是固定的,不会更改,而访问令牌可能会过期。

问题是:应用程序如何知道这是一个访问令牌还是API密钥。我的意思是,好的,比方说,在我的数据库中,每个用户的数据库中都有一个“api_key”列。

与访问令牌相反,api_key不会过期(尽管用户最终可以旋转它)。正如我所说的,我想要的是同质化的认证处理。

案例1:我自己的web应用程序做API调用

的工作流程如下,使用的OAuth2:

  1. 用户输入自己的电子邮件/密码。
  2. 授权服务器返回临时访问令牌(例如:“abc”)。
  3. 在Web应用程序中,所有API调用都是使用此令牌完成的。例如:“/ payments/1”,授权标题为“Bearer abc”。

好又简单。

案例2:用户有一个API密钥,也不会过期,可以私下在自己的应用程序

显然使用授权机制必须保持不变。所以:

  1. 用户进入他的账户,并且读取他的API密钥是“def”。
  2. 在他们的服务器代码中,他们可以使用相同的身份验证机制执行相同的调用。因此,他可以通过Authorization:“Bearer def”调用“/ payments/1”。

它必须工作。正如你所看到的,两个例子都没有改变。他们访问相同的资源,相同的授权机制......但在一种情况下,我们有一个访问令牌,在其他情况下,我们有一个API密钥。而且我不知道我应该如何从数据库的角度和授权代码中实现这一点。

我有一个潜在的想法是使用不同的认证机制。对于OAuth,它将是“授权:承载访问令牌”,而对于API,它将是基本认证:“授权:基本apiKey”。

听起来不错?

相关问题