AWS Cognito应用客户端多租户:tenant_id与client id/secret关联及识别方案
在Client Credentials模式下给JWT Access Token加Tenant ID的实现方案
核心思路
既然每个client_id都是绑定到特定租户的,那在生成JWT的时候,直接从客户端的关联数据里把tenant_id拿出来,塞到JWT的自定义字段里就行,这是最直接高效的方案。
具体实现步骤
1. 存好Client和Tenant的绑定关系
首先得在你的客户端管理数据库里,给每个client记录加个tenant_id字段,创建client的时候就把它和对应的租户绑定死。举个数据库表结构的例子:
CREATE TABLE oauth_clients ( client_id VARCHAR(255) PRIMARY KEY, client_secret VARCHAR(255) NOT NULL, tenant_id VARCHAR(255) NOT NULL, -- 关联对应的租户ID -- 其他字段比如权限范围、过期时间之类的按需添加 );
2. 改造Token生成逻辑
在处理/oauth2/token接口的client credentials授权请求时:
- 先验证client_id和client_secret的合法性
- 从数据库里查出这个client对应的
tenant_id - 把
tenant_id作为自定义声明加到JWT的payload里。生成的JWT payload大概是这样:
{ "iss": "你的SaaS域名", "sub": "client:xxx-client-id", "aud": "你的API受众标识", "exp": 1719859200, "iat": 1719855600, "tenant_id": "tenant-12345" -- 自定义的租户ID字段 }
要是你用的是现成的OAuth2框架(比如Spring Security OAuth2、Keycloak、Auth0),不用自己手写JWT生成逻辑,直接用框架的自定义Token增强器或者客户端声明映射功能就能搞定,省不少事儿。
3. API认证时直接取Tenant ID
在API网关或者业务服务的认证拦截器里:
- 解析JWT Access Token
- 直接从payload里提取
tenant_id字段 - 把这个值传给业务逻辑,用来做统计、计费或者租户隔离都行
实用建议
- 字段选择:优先自定义
tenant_id:要是不想搞自定义字段,也可以考虑用JWT标准里的azp(Authorized Party)声明,但azp本来是用来标识客户端的,不如自定义tenant_id语义清晰,推荐用后者。 - 别塞敏感数据:JWT里只能放非敏感的标识信息,
tenant_id没问题,但租户的密钥、隐私数据绝对不能放,哪怕JWT是加密的也不行。 - 严格隔离客户端与租户:一个client_id只能绑定一个tenant_id,绝对不能跨租户混绑,不然会出现权限越界的问题。
- 记好关联日志:生成token的时候,把client_id和tenant_id的对应关系记录到日志里,后面排查问题、审计的时候能派上大用场。
- 合理设置Token有效期:M2M场景下token有效期可以适当延长,但建议别超过24小时,同时要支持客户端主动刷新token,避免频繁请求token接口影响性能。
内容的提问来源于stack exchange,提问作者Ning
相关产品推荐
相关产品推荐

