鉴权认证
鉴权方式
石墨 API 授权通过 Access Token 作为接口调用的凭证,接口调用方在对 API 发起请求时,需在 HTTP Header 加入以下授权参数:
Authorization: Bearer <Access Token>
一个 Access Token 对应一个文档,即页面刷新、关闭重新打开或打开其他文档均需要重新生成 Access Token。
授权流程
+--------+ ID/Secret +--------+
| | +-----------------> | |
| | | |
| | Access Token | |
| Client | <-----------------+ | 石墨 |
| | | |
| | Access Token | |
| | +-----------------> | |
+--------+ +--------+
ID/Secret 为石墨提供的
ClientID
、ClientSecret
。
Access Token
Access Token 数据结构如下:
{
"scope": "write",
"tokenType": "bearer",
"accessToken": "70615e7c1e08fc7805c0df0e4dbc595600814f70b2b916c0e737e6ca2f914e7d",
"refreshToken": "70615e7c1e08fc7805c0df0e4dbc595600814f70b2b916c0e737e6ca2f914e7d",
"expireTime": "2018-06-12T09:50:23.000Z"
}
- Access Token 有效期默认为 24 小时,有效期内同一个用户可重复使用该 Access Token 访问同一个文档。
accessToken.scope
scope
指该 Access Token 所具备的访问权限,如是否允许写入数据,用于限制 Access Token 可访问范围,避免 Access Token 泄漏、错误调用 API 等情况。
目前可用值:
名称 | 描述 |
public | 只可访问公开数据。 |
read | 只可访问公开和需验证用户权限的数据。包含 `public` 的权限。 |
write | 可读取和写入数据。包含 `read` 和 `public` 的权限。 |
user | 允许访问所有用户相关 API。包含所有 `user:` 开头的权限。 |
user:create | 允许访问创建用户的 API。 |
和 accessToken.info
不同的是,scope
仅用于判断能否访问指定 API,SDK 服务器会先比较 scope
是否匹配,在比较 info
中的权限:
scope: 'read
能访问用户的信息 (如GET /users/me
) ,但不能执行更新用户信息或创建文件等操作;scope: 'write'
和info.filePermissions.editable: false
的 Access Token 能更新用户信息PATCH /users/:user
,但不能撰写文档,因此POST /files/<GUID>/compose
将会返回401
错误;scope: 'read'
和info.filePermissions.editable: true
的 Access Token 由于scope
不具备写权限,因此POST /files/<GUID>/compose
将会返回401
错误;scope: 'read'
和info: null
因为没有info
信息,该 Access Token 只能访问部分接口POST /files/<GUID>/compose
将会返回401
错误。
accessToken.info
由于 SDK 并不存储用户和文档的具体关系 (如权限) ,因此针对单个 Access Token,需要通过 info
来声明用户对指定文档的权限。
info
仅在 file
资源接口中生效,如获取文件接口 (GET /files/<GUID>
) , 但创建文件接口 (POST /files
) 不需要 info
。
info
需以 JSON 字符串或 JSON object 的形式发送到 SDK 服务器 (如何发送请看获取 Access Token) ,数据格式如下:
{
"fileGuid": "JyRX1679PL86rbTk",
"filePermissions": {
"editable": true,
"commentable": true,
"readable": true
}
}
fileGuid
:为对应的文件的 GUID。
filePermissions
:为用户对该文件所拥有的权限:
名称 | 类型 | 说明 |
---|---|---|
readable | boolean | 对文档的读权限,如允许匿名用户访问文档,但不可编辑。readable 为必填项,仅当 editable 为 true 时可忽略。readonly 已标记为弃用,未来将会删除,请更改为 readable |
editable | boolean | 对文档的编辑权限,会强制指定 readable 为 true |
commentable | boolean | 对文档的评论权限,目前需和 editable 一致 |
获取 Access Token
使用 Client Credentials 获取 Access Token
接口
POST <SHIMO_API>/oauth2/token/
参数说明
Content-Type: application/json
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
clientId | String | Y | 石墨提供的 ClientID |
clientSecret | String | Y | 石墨提供的 ClientSecret |
clientUserId | String | Y | 请求授权的用户标识 |
grantType | String | Y | 授权模式,此处需用 client_credentials |
scope | String | Y | 授权范围,为 write 、read 和 public 中一个 |
info | String | N | 访问指定文档时需要的授权信息,为序列化后的 JSON 字符串 |
clientUserId
什么是 clientUserId
意为所请求授权的用户的身份标识,可以用户 ID、用户名或用户邮箱等。
用于在用户和文档数据不储存在石墨数据库时,和石墨所存储的数据进行用户关联用。
代码示例
const request = require('node-fetch')
fetch('<SHIMO_API>/oauth2/token', {
method: 'POST',
body: JSON.stringify({
clientId: 'shimo',
ClientSecret: 'shimo',
grantType: 'client_credentials',
clientUserId: '1',
scope: 'write',
info: JSON.stringify({
fileGuid: 'JyRX1679PL86rbTk',
filePermissions: {
editable: true,
writeable: true,
readonly: true
}
})
})
})
.then(res => res.json())
.then(body => console.log(body.data))
返回示例
{
"scope": "write",
"tokenType": "bearer",
"accessToken": "70615e7c1e08fc7805c0df0e4dbc595600814f70b2b916c0e737e6ca2f914e7d",
"refreshToken": "70615e7c1e08fc7805c0df0e4dbc595600814f70b2b916c0e737e6ca2f914e7d",
"expireTime": "2018-06-12T09:50:23.000Z"
}
使用 Refresh Token 获取新的 Access Token
不是所有 client 都具备 Refresh Token 权限,如遇到问题,请联系客服。
接口
POST <SHIMO_API>/oauth2/token/
参数说明
Content-Type: application/json
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
clientId | String | Y | 石墨提供的 ClientID |
clientSecret | String | Y | 石墨提供的 ClientSecret |
grantType | String | Y | 授权模式,此处需用 refresh_token |
clientUserId | Number | Y | 请求授权的用户标识 |
refreshToken | String | N | 用于刷新授权码 |
代码示例
const request = require('node-fetch')
fetch('<SHIMO_API>/oauth2/token', {
method: 'POST',
body: JSON.stringify({
grantType: 'refresh_token',
clientUserId: 'shimo',
refreshToken: '70615e7c1e08fc7805c0df0e4dbc595600814f70b2b916c0e737e6ca2f914e7d'
})
})
.then(res => res.json())
.then(body => console.log(body.data))
返回参数
参数 | 类型 | 说明 |
---|---|---|
accessToken | String | 授权码 |
refreshToken | String | 用于刷新授权码 |
scope | String | Access Token 授权的范围 |
expiresIn | String | Access Token 的过期时间 |
tokenType | String | Access Token 类型,默认 bearer |
吊销 Access Token
接口
POST <SHIMO_API>/oauth2/revoke/
参数说明
Content-Type: application/json
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
accessToken | String | Y | 需要吊销的 Access Token |
代码示例
const request = require('node-fetch')
fetch('<SHIMO_API>/oauth2/revoke', {
method: 'POST',
body: JSON.stringify({
accessToken: '70615e7c1e08fc7805c0df0e4dbc595600814f70b2b916c0e737e6ca2f914e7d'
})
})
.then(res => res.json())
.then(body => console.log(body.data))
状态码说明
204
删除成功