为移动应用程序创建API - 身份验证和授权

时间:2010-10-18 22:21:42

标签: api authentication rest oauth mobile-application

概述

我正在为我的应用程序创建一个(REST)API。初始/主要目的是供移动应用程序(iPhone,Android,Symbian等)使用。我一直在研究基于Web的API的身份验证和授权的不同机制(通过研究其他实现)。我已经掌握了大部分基本概念,但我仍在寻找一些领域的指导。我想做的最后一件事就是重新发明轮子,但我找不到任何符合我标准的标准解决方案(不过我的标准是我的误导,所以也可以随意批评)。此外,我希望API对于使用它的所有平台/应用程序都是相同的。

OAUTH

我会继续向oAuth反对,因为我知道这可能是第一个提供的解决方案。对于移动应用程序(或更具体地说是非Web应用程序),离开应用程序(转到Web浏览器)进行身份验证似乎是错误的。此外,没有办法(我知道)浏览器将回调返回给应用程序(特别是跨平台)。我知道有几个应用程序可以做到这一点,但它只是感觉不对,并且在应用程序用户体验中取得了突破。

要求

  1. 用户在应用程序中输入用户名/密码。
  2. 每个API调用都由调用应用程序识别。
  3. 开销保持在最低限度,auth方面对开发人员来说非常直观。
  4. 该机制对最终用户(他们的登录凭证未公开)以及开发人员(他们的应用程序凭据未公开)都是安全的。
  5. 如果可能,不要求https(绝不是硬性要求)。
  6. 我目前关于实施的想法

    外部开发者将请求API帐户。他们将得到一个apikey和apisecret。每个请求至少需要三个参数。

    • apikey - 在注册时发给开发人员
    • timestamp - 兼作给定apikey的每条消息的唯一标识符
    • hash - 时间戳的哈希值+ apisecret

    需要apikey来识别发出请求的应用程序。时间戳的作用与oauth_nonce类似,可以避免/减轻重放攻击。哈希确保请求实际是从给定apikey的所有者发出的。

    对于经过身份验证的请求(代表用户完成的请求),我仍然未决定使用access_token路由或用户名和密码哈希组合。无论哪种方式,在某些时候都需要用户名/密码组合。因此,当它发生时,将使用几条信息(apikey,apisecret,timestamp)+密码的散列。 我喜欢这方面的反馈。仅供参考,他们必须首先对密码进行哈希处理,因为我没有在没有散列的情况下将密码存储在我的系统中。

    结论

    仅供参考,这不是一般要求如何仅在应用程序内处理身份验证和授权的请求。

    随机思考/奖金问题

    对于仅需要apikey作为请求的一部分的API,如何防止apikey所有者以外的其他人查看apikey(因为明确发送)并过多地请求将其推送到超出使用限制?也许我只是在想这个,但是不应该有一些东西需要验证是否已向apikey所有者验证了请求?在我的情况下,这是apisecret的目的,它不会被显示/传输而不被散列。

    说到哈希,md5和hmac-sha1怎么样?使用足够长的数据(即apisecret)对所有值进行哈希处理真的很重要吗?

    我以前考虑过向用户密码哈希添加每用户/行盐。如果我这样做,应用程序如何能够在不知道使用盐的情况下创建匹配的哈希?

5 个答案:

答案 0 :(得分:43)

我正在考虑在我的项目中执行此登录部分的方式是:

    登录前
  1. 用户从服务器请求login_token。这些是根据请求生成并存储在服务器上的,并且可能具有有限的生命周期。

  2. 登录应用程序计算用户密码的哈希值,然后使用login_token哈希密码获取值,然后返回login_token和组合哈希值。< / p>

  3. 服务器检查login_token是否已生成,将其从有效login_token列表中删除。然后,服务器将其存储的用户密码哈希值与login_token组合,并确保它与提交的组合令牌匹配。如果匹配,则表示您已对用户进行了身份验证。

  4. 这样做的好处是你永远不会在服务器上存储用户的密码,密码永远不会以明文形式传递,密码哈希只会在明确的帐户创建中传递(尽管可能有办法解决这个问题),以及它应该对重放攻击安全,因为login_token在使用时会从数据库中删除。

答案 1 :(得分:13)

这是一个很多问题,我想很多人都没有设法一直读到最后:)

我对Web服务身份验证的体验是人们通常过度使用它,而且问题只与您在网页上遇到的问题相同。可能非常简单的选项包括登录步骤的https,返回令牌,要求将其包含在将来的请求中。您还可以使用http基本身份验证,只需传递标题中的内容即可。为了增加安全性,请经常旋转/过期令牌,检查请求是否来自同一个IP块(这可能会因为移动用户在小区之间移动而变得混乱),与API密钥或类似组合。或者,在对用户进行身份验证之前,执行oauth的“请求密钥”步骤(有人在之前的回答中建议这一点并且这是一个好主意),并将其用作生成访问令牌的必需密钥。

我尚未使用过的另一种选择,但我听说过很多关于oAuth的设备友好替代方案xAuth。看看它,如果你使用它,那么我真的很想知道你的印象是什么。

对于散列,sha1稍微好一些,但不要挂断它 - 无论设备能够轻松(并且在性能意义上很快),实现都可能没问题。

希望有所帮助,祝你好运:)

答案 2 :(得分:9)

Twitter通过支持他们称之为xAuth的变体来解决oAuth中的外部应用程序问题。不幸的是,已经出现了许多其他具有此名称的方案,因此可能会让人感到困惑。

协议 oAuth,除了它跳过请求令牌阶段并且在收到用户名和密码后立即发出访问令牌对。 (从step E here开始。)此初始请求和响应必须受到保护 - 它以明文形式发送用户名和密码并接收访问令牌和秘密令牌。一旦配置了访问令牌对,初始令牌交换是通过oAuth模型还是xAuth模型与会话其余部分的客户端和服务器无关。这样做的好处是,您可以利用现有的oAuth基础架构,并为移动/ Web /桌面应用程序提供几乎相同的实现。主要的缺点是应用程序被授予访问客户端用户名和密码的权限,但看起来您的要求强制要求这种方法。

在任何情况下,我都同意你的直觉以及其他几位回答者的直觉:不要试图从头开始构建新东西。安全协议可以很容易地启动,但总是很难做到,并且它们变得越复杂,第三方开发人员就越不可能实现它们。你的假设协议非常类似于o(x)Auth - api_key / api_secret,nonce,sha1哈希 - 但是你不需要使用你的开发人员需要自己创建的许多现有库中的一个。

答案 3 :(得分:8)

那么您所追求的是某种服务器端身份验证机制,它将处理移动应用程序的身份验证和授权方面?

假设是这种情况,那么我会按如下方式处理它(但只是'因为我是Java开发人员所以C#的人会以不同的方式做到这一点):

RESTful身份验证和授权服务

  1. 这仅适用于HTTPS以防止窃听。
  2. 它将基于RESTEasySpring SecurityCAS的组合(适用于多个应用程序的单点登录)。
  3. 它适用于浏览器和支持Web的客户端应用程序
  4. 将有一个基于网络的帐户管理界面,允许用户编辑他们的详细信息,以及管理员(针对特定应用程序)更改授权级别
  5. 客户端安全库/应用程序

    1. 对于每个支持的平台(例如 Symbian,Android,iOS等)创建一个 适合执行 本机安全库 平台的语言(例如Java, ObjectiveC,C等)
    2. 图书馆 应该管理HTTPS请求 使用可用的API形成 对于给定的平台(例如Java 使用URLConnection等)
    3. 消费者的一般认证和 授权库('cos that's 所有这些都将编码到特定的 界面,如果它不会很高兴 永远改变所以确保它是非常的 灵活。遵循现有设计 选择如Spring Security。
    4. 所以现在30,000英尺的视图已经完成,你怎么去做呢?那么,使用浏览器客户端在服务器端基于列出的技术创建认证和授权系统并不困难。与HTTPS结合使用时,框架将基于由身份验证过程生成的共享令牌(通常表示为cookie)提供安全过程,并在用户希望执行某些操作时使用。无论何时发生任何请求,客户端都会将此令牌呈现给服务器。

      对于本地移动应用程序,您似乎正在寻求执行以下操作的解决方案:

      1. 客户端应用程序具有定义的访问控制列表(ACL),用于控制对方法调用的运行时访问。例如,给定用户可以从方法中读取集合,但是他们的ACL仅允许访问其名称中具有Q的对象,因此集合中的某些数据被安全拦截器拉动。在Java中,这很简单,您只需在调用代码上使用Spring Security注释并实现合适的ACL响应过程。在其他语言中,您可能需要自己提供可以调用安全库的样板安全代码。如果该语言支持AOP(面向方面​​编程),那么在这种情况下最充分地使用它。
      2. 安全库将完整的授权列表缓存到当前应用程序的私有内存中,以便它不必保持连接。根据登录会话的长度,这可能是一次性操作,永远不会重复。
      3. 无论您做什么,都不会尝试创建自己的安全协议,或者通过默默无闻来使用安全性。你永远无法为此编写一个比当前可用且免费的算法更好的算法。此外,人们相信众所周知的算法。因此,如果您说安全库使用SSL,HTTPS,SpringSecurity和AES加密令牌的组合为本地移动应用程序提供授权和身份验证,那么您将立即在市场中获得信誉。

        希望这会有所帮助,并祝你好运。如果您想了解更多信息,请告诉我 - 我已经编写了很多基于Spring Security,ACL等的Web应用程序。

答案 4 :(得分:5)

参加派对的时间已经很晚了,但我想为对这个问题感兴趣的人提出一些额外的要点。我为一家从事移动API安全解决方案(approov)的公司工作,所以整个领域都与我的兴趣无关。

首先,在尝试保护移动API时要考虑的最重要的事情是对您有多大价值。银行的正确解决方案与正确做事的人的正确解决方案不同。

在提议的解决方案中,您提到至少需要三个参数:

  • apikey - 在注册时发给开发者
  • timestamp - 兼作给定apikey的每条消息的唯一标识符
  • hash - 时间戳的哈希值+ apisecret

这意味着对于某些API调用,不需要用户名/密码。这对于您不想强制登录的应用程序非常有用(例如,在在线商店中浏览)。

这与用户身份验证的问题略有不同,更像是对软件的身份验证或证明。没有用户,但您仍希望确保您的API没有恶意访问权限。因此,您使用API​​密钥对流量进行签名,并将访问API的代码标识为正版。此解决方案的潜在问题是,您必须在应用程序的每个版本中泄露秘密。如果有人可以提取秘密,他们可以使用您的API,冒充您的软件,但做任何他们喜欢的事情。

为了应对这种威胁,根据数据的价值,您可以做很多事情。 混淆是一种简单的方法,可以更难以提取秘密。有一些工具可以帮到你,对Android来说更是如此,但是你仍然必须拥有生成哈希的代码,并且一个技术娴熟的人可以随时调用直接进行哈希的函数。

另一种减少过度使用不需要登录的API的方法是限制流量,并可能识别和阻止可疑的IP地址。您想要的努力程度在很大程度上取决于您的数据的价值。

除此之外,您可以轻松地开始进入我的日常工作领域。无论如何,这是保护API的另一个方面,我认为这很重要并且想要标记。