仅应用程序身份验证和 OAuth 2.0 不记名令牌

概述

Twitter 使应用程序能够代表其自身(而不是代表特定用户)发出经过身份验证的请求。Twitter 的实现基于 OAuth 2 规范客户端凭据授予流程。

仅应用程序身份验证不包含任何用户情景,是一种应用程序代表自身发出 API 请求的身份验证形式。此方法适用于只需要以只读方式访问公开信息的开发者。 

你可使用应用使用者 API 密钥或不记名令牌来执行仅应用程序身份验证。这意味着你向 Twitter API 发出的请求不得要求用户必须通过身份验证。

借助仅应用程序身份验证,可执行以下操作:

  • 拉取用户时间线
  • 访问任何账号的好友和关注者
  • 访问列表资源
  • 搜索推文

 

请注意,仍然需要 OAuth 1.0a 才能代表用户发出请求。 API 参考页面介绍了使用 API ​​所需的身份验证方法。你将需要用户身份验证、用户情景以及访问令牌才能执行以下操作:

  • 发布推文或其他资源
  • 搜索用户
  • 使用任何地理端点
  • 访问私信或账号凭据
  • 检索用户的邮件地址

 

验证流程

要使用此方法,你需要使用不记名令牌。可通过 POST oauth2/token 端点来传递使用者密钥和机密,从而生成不记名令牌。 

仅应用程序验证流程遵循以下步骤:

  • 应用程序将其使用者密钥和机密编码为一组经过特殊编码的凭据。
  • 应用程序向 POST oauth2/token 端点发出请求,以使用这些凭据交换不记名令牌。
  • 在访问 REST API 时,应用程序使用不记名令牌进行验证。

由于无需对请求进行签名,因此该方法比标准的 OAuth 1.0a 模式简单得多。

 

关于仅应用程序验证

令牌即密码

请记住,使用者密钥和机密以及不记名令牌本身就可授予代表应用程序发出请求的权限。这些值应与密码一样被视为敏感信息,并且不得分享或分发给不受信任的各方。

需要 SSL

所有请求(获取和使用令牌)都必须使用 HTTPS 端点。请按照使用 TLS 连接到 Twitter API 中所述的最佳实践操作,注意应始终验证对等方。

没有用户情景

使用仅应用程序验证发出请求时,没有“当前用户”的概念。因此,将仅应用程序验证用于 POST statuses/update 之类的端点将不起作用。如需详细了解如何代表用户发出请求,请参阅使用 OAuth

速率限制

应用程序有两种速率限制池。

使用访问令牌(也称为用户情景)代表用户发出的请求所消耗的速率限制上下文与仅应用程序身份验证中使用的速率限制上下文不同。换言之,代表用户发出的请求将不会消耗通过仅应用验证提供的速率限制,通过仅应用验证发出的请求不会消耗基于用户的验证中使用的速率限制。

你可以使用 GET application/rate_limit_status 端点查看速率限制,该端点支持仅应用程序身份验证。使用应用程序不记名令牌向此方法发出请求后,你将收到一个响应,指出当前窗每项资源的速率限制上下文。你会收到一个“application”字段,其值为应用程序的使用者密钥,而不会收到指示正在使用的访问令牌的“rate_limit_context”字段。

{
  "rate_limit_context": {
      "application": "nXtEH7H0mi0qT8kSyo7DQ"
  },
  "resources": {
    "search": {
      "/search/tweets": {
        "limit": 450,
        "remaining": 420,
        "reset": 1362436375 }
    }
  }
}

 

请详细阅读 API 速率限制查看限制

 

发出仅限应用程序的请求

步骤 1:对使用者密钥和机密进行编码

按照以下步骤将应用程序的使用者密钥和机密编码为一组凭据,来获得不记名令牌:

  1. URL 根据 RFC 1738 对使用者密钥和使用者机密进行编码。请注意在编写时,实际上不会更改使用者密钥和机密,但仍应执行该步骤,以防这些值的格式将来发生更改。
  2. 将已编码的使用者密钥、冒号字符“:”和已编码的使用者机密串联成一个字符串。
  3. 对上一步中的字符串进行 Base64 编码

下面是显示此算法结果的示例值。请注意,本页中使用的使用者机密仅用于测试目的,不适用于实际请求。

使用者密钥 xvz1evFS4wEEPTGEFPHBog
使用者机密 L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg
RFC 1738 编码的使用者
密钥(未更改)
xvz1evFS4wEEPTGEFPHBog
RFC 1738 编码的使用者
机密(未更改)
L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg
不记名令牌凭据 xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg
Base64 编码的不记名令牌凭据 :: eHZ6MWV2RlM0d0VFUFRHRUZQSEJvZzpMOHFxOVBaeVJnNmllS0dFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==

步骤 2:获取不记名令牌

必须向 POST oauth2/token 发出请求,使用步骤 1 中计算出的值交换不记名令牌:

  • 该请求必须是一个 HTTP POST 请求。
  • 请求必须包含 Authorization 标头,其值为 Basic <base64 encoded value from step 1>.
  • 请求必须包含 Content-Type 标头,其值为 application/x-www-form-urlencoded;charset=UTF-8.
  • 请求的正文必须为 grant_type=client_credentials

示例请求(已包装授权标头):

POST /oauth2/token HTTP/1.1
Host: api.twitter.com
User-Agent: My Twitter App v1.0.23
Authorization: Basic eHZ6MWV2RlM0d0VFUFRHRUZQSEJvZzpMOHFxOVBaeVJn
                     NmllS0dFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 29
Accept-Encoding: gzip

grant_type=client_credentials

 

如果请求的格式正确,则服务器将以 JSON 编码的有效负荷进行响应:

示例响应:

HTTP/1.1 200 OK
Status: 200 OK
Content-Type: application/json; charset=utf-8
...
Content-Encoding: gzip
Content-Length: 140

{"token_type":"bearer","access_token":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}

 

应用程序应验证与返回对象的 token_type 密钥关联的值是否为 bearer。与 access_token 密钥关联的值就是不记名令牌。

请注意,一个不记名令牌一次只对一个应用程序有效。使用相同的凭据向 /oauth2/token 发出另一个请求将返回同一令牌,直到该令牌失效为止。

步骤 3:使用不记名令牌验证 API 请求

不记名令牌可用于向支持仅应用程序验证的 API 端点发出请求。要使用不记名令牌,请构造一个普通的 HTTPS 请求,并添加一个值为 Bearer <base64 bearer token value from step 2>. Signing is not required.Authorization 标头。

示例请求(已包装授权标头):

GET /1.1/statuses/user_timeline.json?count=100&screen_name=twitterapi HTTP/1.1
Host: api.twitter.com
User-Agent: My Twitter App v1.0.23
Authorization: Bearer AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAA
                      AAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Accept-Encoding: gzip

 

使不记名令牌失效

如果不记名令牌因任何原因遭到破解或需要使之失效,请调用 POST oauth2/invalidate_token

示例请求(已包装授权标头):

POST /oauth2/invalidate_token HTTP/1.1
Authorization: Basic eHZ6MWV2RlM0d0VFUFRHRUZQSEJvZzpMOHFxOVBaeVJn
                     NmllS0dFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==
User-Agent: My Twitter App v1.0.23
Host: api.twitter.com
Accept: */*
Content-Length: 119
Content-Type: application/x-www-form-urlencoded

access_token=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

 

示例响应:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 127
...

{"access_token":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}

 

常见错误案例

本部分介绍了协商和使用不记名令牌时出现的一些常见错误。请注意,此处并未涵盖所有可能的错误响应,需注意未处理的错误代码和响应。

用于获取或撤销不记名令牌的请求无效

尝试:

  • 使用无效的请求获取不记名令牌(例如,去掉 grant_type=client_credentials)。
  • 使用不正确或失效的应用凭据获取或撤销不记名令牌。
  • 使不正确或已撤销的不记名令牌无效。
  • 在短时间内过于频繁地获取不记名令牌。

将导致:

HTTP/1.1 403 Forbidden
Content-Length: 105
Content-Type: application/json; charset=utf-8
...

{"errors":[{"code":99,"label":"authenticity_token_error","message":"Unable to verify your credentials"}]}

 

API 请求包含无效的不记名令牌

使用不正确或已撤销的不记名令牌发出 API 请求将导致:

HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Content-Length: 61
...

{"errors":[{"message":"Invalid or expired token","code":89}]}

 

在不支持仅应用程序验证的端点上使用不记名令牌

使用不记名令牌请求需要用户情景(例如 statuses/home_timeline)的端点将导致:

HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
Content-Length: 91
...

{"errors":[{"message":"Your credentials do not allow access to this resource","code":220}]}