语雀支持标准的 OAuth2 authorization code 授权模式




Web 应用流程


流程


  1. 用户被重定向以请求他们的语雀身份
  2. 用户被语雀重定向回你的网站
  3. 你的应用使用用户的 access token 访问 API

时序图



1. 将用户重定向到语雀授权页


GET https://www.yuque.com/oauth2/authorize


参数

参数名

类型

描述

client_id 

string 

语雀应用分配的 client_id

scope 

string 

要求用户授权的 权限范围,多个权限用逗号分隔,例如: doc,repo,group:read

redirect_uri 

string 

重定向地址,授权完成后会跳转到这个路径,并带上临时授权 code

state 

string 

OAuth 规范中的 state,会透传到回调的 redirect_uri 参数

response_type 

string 

固定值: code

2. 用户被重定向回应用回调地址


用户确认授权后,将被重定向到应用指定的回调地址,并附带 state 和 code 参数。


参数

参数名

类型

描述

code 

string 

用户的临时授权码,用于后续流程中调用语雀接口,换取用户的 access_token

state 

string 

上一步流程中的 state 参数透传

3. 通过 code 换取用户 token


POST https://www.yuque.com/oauth2/token


参数

参数名

类型

描述

client_id 

string 

语雀应用分配的 client_id

client_secret 

string 

语雀应用分配的 client_secret

code 

string 

前序流程中获取到的临时授权码

grant_type 

string 

固定值 authorization_code

响应


响应是一个 JSON 格式的字符串,包含用户授权后的 token,该 token 只能访问用户授权范围内的 API。


{ 
  "access_token": "am9ic0B5dXF1ZS5jb20=",
  "token_type": "bearer",
  "scope": "repo,doc"
}


4. 通过 token 来访问语雀的 API


curl -H 'X-Auth-Token: ${token}' https://www.yuque.com/api/v2/user



非 Web 应用流程


有些应用可能并没有服务端支持,而是一个纯客户端应用(浏览器插件、命令行工具),为了便于这类应用的授权,语雀提供了一种非 Web 应用的授权流程。


注意:此流程需要将 client_secret 下发到客户端中,有一定秘钥泄露的风险。


流程


  1. 客户端随机生成一个 40 位长度的 code。
  2. 将用户重定向到语雀的授权页,参数用 client_secret 加签。
  3. 用户确定授权,应用通过 code 调用语雀接口换取用户的 token。
  4. 通过 token 访问语雀开放 API。


1. 客户端生成 code


客户端自行生成一个长度为 40 的随机字符串(字母和数字组成),后续流程中需要用到。


2. 将用户重定向到语雀授权页


GET https://www.yuque.com/oauth2/authorize


参数

参数名

类型

描述

client_id 

string 

语雀应用分配的 client_id

code 

string 

上一步中生成的 code

response_type 

string 

固定值: code

scope 

string 

要求用户授权的 权限范围,多个权限用逗号分隔

例如: doc,repo,group:read

timestamp 

string 

当前时间的时间戳(毫秒值)

例如:1530243304828

sign 

string 

签名,签名方式见下面的描述


需要对参数签名语雀才会认为是合法的应用发起的授权请求,签名方式如下:


所有的参数以字母顺序排序( client_id , code , response_type , scope , timestamp ),将所有的参数值 URL encode,最后用 & 拼接到一起:


client_id=IDg4dfUS5vaNo05vqrXa&code=2Omo46aDfdssxjpffffptMAbmuj7xu8dBURRsHun&response_type=code&scope=doc%2Crepo&timestamp=1530243304828


将拼接好的字符串,使用 sha1 加签,秘钥为 client_secret,并对加签后的结果进行 base64 编码拿到字符串,设置到 sign 参数即可。


// Node.js 参考代码
function sign(query, secret) {
  const signString = [
    'client_id', 'code', 'response_type', 'scope', 'timestamp',
  ].map(key => `${key}=${encodeURIComponent(query[key] || '')}`).join('&');
  return crypto.createHmac('sha1', secret)
    .update(signString)
    .digest()
    .toString('base64');
}


3.通过 code 调用语雀接口换取用户的 token


这个流程用户授权完成之后,不会再把 code 通过 URL 返回,客户端可以直接通过第一步中随机生成的 code 原始值调用语雀的接口换取用户的 token,这一步不需要再传递 client_secret


POST https://www.yuque.com/oauth2/token


参数

参数名

类型

描述

client_id

string

语雀应用分配的 client_id

code

string

前序流程中获取到的临时授权码

grant_type

string

固定值 client_code

响应


响应是一个 JSON 格式的字符串,包含用户授权后的 token,该 token 只能访问用户授权范围内的 API。


{ 
  "access_token": "am9ic0B5dXF1ZS5jb20=",
  "token_type": "bearer",
  "scope": "repo,doc"
}



一般来说,由于用户确认授权后不会回调,所以在将用户重定向到语雀授权页之后就可以开始轮询语雀的授权接口了(请注意轮询间隔时长控制在 3s 左右)。


4. 通过 Token 来访问语雀的 API


后续流程和 OAuth 授权一样,通过 token 即可以授权用户的身份访问 API。


curl -H 'X-Auth-Token: ${token}' https://www.yuque.com/api/v2/user


Node.js 客户端


Node.js 版本的授权过程已经封装成了一个模块 yuque-auth,如果应用是 Node.js 编写,可以直接使用,其他语言也可以参考该模块自行实现。