# 用户许可的应用间授权
假如你的公司是一家做社交通讯业务的公司,现在有另外一家公司想通过调用你的业务 API 开发一个聊天记录整理导出的工具,并且已经和你的公司签约合作。现在你想要安全地将用户信息授权给这家公司,你期望:
- API 的调用只开放给合作伙伴公司。
- 不同的合作伙伴拥有的访问权限不同,能够访问的业务 API 也不同。
- 合作伙伴公司从业务 API 获取自己公司的用户数据之前,必须先征得用户的同意。
- 如果将来终止合作,或者发生变化,希望能够收回某些数据的权限或者完全禁用。
# 权限管理与分配
首先在 Authing 创建两个用户。分别为 user1@123.com 和 user2@123.com。
在 Authing 创建一个应用,假设我们的社交软件叫做「蒸汽聊天」,那么应用名字就叫做「蒸汽聊天」。
在应用详情,点击授权选项卡,切换到数据资源 tab,然后点击添加。
API 资源、数据资源、UI 资源在本质上没有区别,类型仅用于管理层面上的区分,创建良好的资源分类能够方便管理员快速聚焦不同的资源。
我们创建一个聊天数据资源,定义增删改查几个操作,最后点击保存。
然后在资源授权中添加授权规则。
被授权主体选择 user1@123.com 和 user2@123.com,资源类型选择聊天数据,然后点击确定。
然后我们创建一个编程访问账号,将来会交给调用方。
如果将编程访问账号删除,调用方将会失去获取用户授权的能力。
# AccessToken 过期时间
当你创建编程访问账号时,需要指定 AccessToken 过期时间。Authing 在颁发 AccessToken 时使用 RS256 签名算法进行签名,以确保 AccessToken 不会被篡改。
Token 签名是 JWT 中的一部分,更多内容请参考 JWT 释义及使用。
- RS256 是一种非对称签名算法,Authing 持有私钥对 Token 进行签名,JWT 的消费者使用公钥来验证签名。 RS256 签名算法,有以下好处:
- 任何人都可以使用应用公钥验证签名,签名方一定是 Authing。
- 无私钥泄露风险,如果你使用 HS256 但泄露了应用密钥,需要刷新密钥并重新部署所有 API。 关于签名问题更多内容请参考验证 Token。
下面,我们为用户添加资源权限,在资源授权卡片,点击添加。
然后我们为 user1@123.com、user2@123.com 用户添加所有消息数据的所有操作权限,最后点击确定。 到此管理员进行权限管理的操作就全部结束了。
# 获取具备权限的 AccessToken
调用方需要通过 OIDC 授权码模式从资源方获得资源授权。资源方的用户会参与到授权过程,经过用户的授权后,Authing 会签发具备权限 scope 且主体为资源持有者的 AccessToken。 首先需要拼接授权链接:
https://{应用域名}.authing.cn/oidc/auth?client_id={应用ID}&response_type=code&scope=openid email message&redirect_uri={调用方业务地址}&state={随机字符串}
其中的 scope 参数中可以填写上面步骤中定义的资源以及相应操作,具体格式如下。
# Scope 权限项目规范
Authing 的 scope 权限项目以空格分隔,每一项的格式是资源标识符:资源操作
。
以下是 Authing 支持的所有 scope 格式:
book:1:read
含义为编号为 1 的书籍资源的读取权限
book:*:read
含义为所有书籍资源的读取权限
book:read
含义为所有书籍资源的读取权限
book:*:*
含义为所有书籍资源的所有操作权限
book:*
含义为所有书籍资源的所有操作权限
book
含义为所有书籍资源的所有操作权限
*:*:*
含义为所有资源的所有操作权限
*:*
含义为所有资源的所有操作权限
*
含义为所有资源的所有操作权限
例如上面定义了 message
资源和 message
资源的 create
操作,这里的 scope 中可以填写 message:create
内容。
调用方应该引导用户点击此链接。用户点击后会跳转到认证页面。
用户完成登录后,会跳转到调用方的业务地址。并在 URL 中携带授权码 code 参数。
接下来需要使用授权码 code 和编程访问账号的 Key 和 Secret,换取用户的 AccessToken 和 IdToken。有关 OIDC 授权码模式的更多信息请查看文档。
可以看到用户的 AccessToken 中具备 message 权限 scope。token 的受众(aud)是编程访问账号 Key。AccessToken 的含义是:调用方 aud 具备资源所有者 sub 的 scope 权限,颁发者是 iss。资源方可以根据 AccessToken 中的信息进行权限校验。
# 添加 API 鉴权拦截器
在 Authing 定义了 API 之后,你需要在你的实际业务 API 接口增加 API 鉴权拦截器,对于受保护的资源,只放行携带了合法的 AccessToken 且具备所需权限的来访者。 代码示例如下:
var express = require('express');
var app = express();
var jwt = require('express-jwt');
var jwks = require('jwks-rsa');
var port = process.env.PORT || 8080;
var jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: 'https://{应用域名}.authing.cn/oidc/.well-known/jwks.json',
}),
audience: '{编程访问账号 ID}',
issuer: 'https://{应用域名}.authing.cn/oidc',
algorithms: ['RS256'],
});
// 检验 AccessToken 合法性
app.use(jwtCheck);
app.post('/article', function(req, res) {
// 检验 AccessToken 是否具备所需要的权限项目
if (!req.user.scope.split(' ').incldues('write:article')) {
return res.status(401).json({ code: 401, message: 'Unauthorized' });
}
res.send('Secured Resource');
});
app.listen(port);
有关 Token 检验的其他内容请参考验证 Token。