Oauth2

lisztli edited this page Apr 20, 2012 · 3 revisions
Clone this wiki locally

饭否API OAuth2认证

饭否网可以使用OAuth2作为验证与授权协议,目前只支持网站类型的应用。

用户授权第三方应用成功之后,应用会得到一个access token, 使用这个 access token, 应用可以访问饭否API2来读取、写入数据。下面将描述网站类型的应用如何获取用户的access token

申请饭否应用

使用饭否OAuth需要在v2ex发帖申请一个饭否应用,申请时请写明以下信息:

  • 应用名称
  • 开发者饭否id
  • 应用主页
  • 应用回调地址(此地址用于授权时检查,必须与下文中提及的redirect_uri一致)

管理员会及时批准该应用,之后开发者可以在 饭否应用详细信息 看到应用的详细信息,以下几项会在后面的文档中使用

  • ClientID
  • ClientSecret
  • AuthorizeURL
  • AccessTokenURL

开发者拿到应用的详细信息之后,就可以进行认证了

第三方应用认证流程

网站类型的第三方应用获取授权应遵循以下流程

重定向用户到应用授权页面

第三方应用首先将用户重定向接到饭否的用户授权页面(AuthorizeURL),并且在url中附带应用的client_idredirect_uriresponse_type=code,url具体的格式为:

AuthorizeURL?redirect_uri=$redirect_uri&response_type=code&client_id=$client_id

其中的$redirect_uri是开发者申请应用时提供的应用回调地址,$client_id是开发者在饭否应用详细信息 看到的ClientID

例如:

https://fanfou.com/oauth2/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Foauth2%2Fauthorize&response_type=code&client_id=36ba8914e5f2b8888f965a507fc3928c

饭否提供了一个“使用饭否帐号登录”的图标, 开发者可以使用这个图标来提示用户登录

使用饭否登录

用户阅读授权说明并同意第三方应用访问个人数据

用户授权页会提示用户“第三方应用希望操作你在饭否伤的数据”,用户此时可以选择“同意”或者“拒绝”。

用户授权页面

用户拒绝向第三方应用授权

用户拒绝向第三方应用授权后,饭否会将用户重定向会开发者的页面,并且带上错误信息。具体格式为:

redirect_uri?error=access_denied

此时开发者可以自行处理此错误

用户同意向第三方应用授权

用户同意向第三方应用授权后,饭否会将用户重定向会开发者的页面,并且带上authorization code。具体格式为:

redirect_uri?code=$authorization_code

例如:

http://localhost:8080/oauth2/authorize?code=663468c87e46789ca58356712d580424

第三方应用使用authorization code来交换用户的access token

第三方应用获取authorization code之后,就可以使用它来向服务器交换用户的access tokenauthorization code在30秒之后过期,所以第三方应用必须在30秒内用authorization code来交换access token),具体方式为发起如下如下请求:

AccessTokenURL?client_id=$client_id&
client_secret=$client_secret&
redirect_uri=$redirect_uri&
code=$authorization_code&
grant_type=authorization_code

其中的$client_id$client_secret$redirect_uri都是饭否应用详细信息显示的信息;$code是饭否返回的authorization_code

如果请求的方式正确,饭否将会以json的方式返回access_token、token有效期(expires_in,单位为秒)、应用的授权范围(scope,暂时未生效)和refresh_token(用于刷新access_token,详见refresh_token。例如:

{
    "access_token": "~68NKILzDyRs-c538eb0be6ce843ac6ca3c7fc81a0e72",
    "expires_in": 3600,
    "scope": null,
    "refresh_token": "~68NKILzDyRs-82671540cdf1f716a87a9d95c2fbce0a"
}

你可以使用如下python代码片段来向服务器交换access token

params = {'client_id': CLIENT_ID
          'redirect_uri': REDIRECT_URI,
          'client_secret': CLIENT_SECRET,
          'code': code_from_fanfou,
          'grant_type': 'authorization_code'}
request = urllib2.Request(AccessTokenURL,
                          urllib.urlencode(params))
response = urllib2.urlopen(request)
body = response.read()
access_results = json.loads(body)

使用refresh token来刷新access token

出于安全考虑,access_token的有效期被设置为3600秒,超过这个时间之后,access_token便无法继续使用,这时候需要使用服务器返回的refresh_token来刷新access_token, 刷新的方法是向https://fanfou.com/oauth2.token使用POST方法发送如下字段client_idclient_secretredirect_urigrant_typerefresh_token

例如:

curl "https://fanfou.com/oauth2.token" -d"client_id=36ba8914e5f2b8888f965a507fc3928c&client_secret=d0b8ff1f91964453b542bbcfb0c447c0&redirect_uri=http://localhost:8080/oauth2/authorize&grant_type=refresh_token&refresh_token=~68NKILzDyRs-82671540cdf1f716a87a9d95c2fbce0a"

如果参数全部正确无误,服务器则会返回新的access_tokenrefresh_token(因为refresh_token也会1209600秒之后过期),应用应该使用返回的值替换旧的token。

一次成功的refresh_token请求返回如下结果:

{
    "access_token": "~68NKILzDyRs-7299164989ecc7308fe5933b78bf69e7",
    "expires_in": 3600,
    "scope": { },
    "refresh_token": "~68NKILzDyRs-5fd98ab15eec14bc51ff1fdd1bdf4819"
}

使用access token来访问饭否APIV2

第三方应用凭有效的access_token,通过饭否API,可以获取用户权限,访问用户数据。 获取用户权限的方法是在POSTGET中加上如下参数oauth_token=$access_token,例如,可以使用curl来访问用户的个人信息:

curl "http://api.fanfou.com/account/verify_credentials.json?oauth_token=~68NKILzDyRs-c538eb0be6ce843ac6ca3c7fc81a0e72"