构建API密钥和访问令牌

时间:2015-04-16 21:40:32

标签: api rest oauth

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

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

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

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

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

    我不确定的一点是客户的概念。似乎在规范中,客户端更像是外部应用程序。不过我可以在这里实际使用这个概念吗?

    例如,每个“项目”实际上是一个不同的客户端(虽然这里的客户端是相同的应用程序,而不是第三方开发人员创建的应用程序)。

    因此,如果用户A在系统上创建帐户,则将使用长期访问令牌(也称为API密钥)自动创建客户端A,其中访问令牌绑定到客户端A.例如,这可以用于直接在他的代码上执行API调用。

    然后,如果用户A登录仪表板,将创建一个临时访问令牌,但这次没有应用程序,但与用户关联,寿命很短。

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

    谢谢!

3 个答案:

答案 0 :(得分:14)

我认为你不应该考虑" API密钥"替代访问令牌。

您无论如何都必须使用访问令牌来承担请求之间的身份验证,因此您实际使用" API密钥建模的内容"不是通常的承载令牌的替代品,而是提供其他授权类型来请求令牌的不同客户端。

我个人实施的流程如下:

  1. 用户使用密码授权类型进行身份验证,每个用户都有一个公共客户端(即您的"网络应用"客户端,这是公开的,即它没有client_secret )。
  2. 然后,用户可以创建自己的客户端。根据OAuth2规范,这些规范不公开,因此它们将包含client_idclient_secret。这些就是你所说的" API密钥"。
  3. 然后,用户将能够通过其客户端请求访问令牌,具有您想要支持的任何给定授权类型(例如,直接客户端凭证,授权代码,隐式,第三方等)。您将不得不强调有关如何处理客户端凭据的适当安全措施。
  4. 显然,您必须以客户可以属于特定用户的方式实施您的OAuth2服务器,并且具有不同的可接受授权类型(即您可能不希望允许密码授予用户客户端使用,而您可能想要禁止除您的网络应用客户端的密码之外的任何授权类型。

    然后,您将能够在每个客户端或每个授权类型的基础上定义令牌TTL或缺少TTL(例如,通过密码授予请求的访问令牌,仅可由Web应用客户端使用,将具有短TTL,而授权代码授予将提供长寿命令牌 我建议不要完全缺少TTL,而是使用refresh_token授权类型来更新过期的访问令牌。

    此外,您可能必须定义某种授权系统(ACL,RBAC,无论如何),以定义哪个客户端可以执行哪些操作。这意味着每个访问令牌都应包含对用于创建它的客户端的引用。

    所以,总结一下,这是关系:

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

    关于双向的YMMV。

    您应该能够使用任何给定平台的最常见OAuth2服务器实现来实现我所描述的所有内容。

    TL; DR:" API密钥"实际上是OAuth2 客户

答案 1 :(得分:2)

感谢您的回答。

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

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

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

案例1:我自己的网络应用程序执行API调用

工作流程如下,使用OAuth2:

  1. 用户输入他的邮件/密码。
  2. 授权服务器返回临时访问令牌(例如:" abc")。
  3. 在网络应用中,所有API调用都是使用此令牌完成的。例如:" / payments / 1"使用授权标题:" Bearer abc"。
  4. 美好而简单。

    案例2:用户拥有一个API密钥,该密钥不会过期,可以在自己的应用中私下使用

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

    1. 用户进入他的帐户,并读到他的API密钥是" def"。
    2. 在他们的服务器代码中,他们可以使用相同的身份验证机制执行相同的调用。所以他可以打电话给" / payments / 1"授权:" Bearer def"。
    3. 它必须有效。如您所见,两个示例中都没有任何变化。他们访问相同的资源,相同的授权机制......但在一种情况下,我们有一个访问令牌,在其他情况下,我们有一个API密钥。我不知道如何从数据库的角度和授权代码中实现这一点。

      我有一个潜在的想法是使用不同的身份验证机制。对于OAuth,它将是"授权:Bearer accessToken",而对于API,它将是基本身份验证:"授权:基本apiKey"。

      这听起来不错吗?

答案 2 :(得分: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)

希望它能回答你的问题。 亨利