如何配置使Keycloak直接获取的Token可用于ThingsBoard REST API?
ThingsBoard与Keycloak集成API认证问题
问题背景
已经完成ThingsBoard和Keycloak的用户认证集成,通过Keycloak登录ThingsBoard UI完全正常。但调用需要JWT访问令牌的ThingsBoard REST API时遇到了问题:
- 调用Keycloak令牌端点(
POST https://<keycloak url>/realms/iuoc/protocol/openid-connect/token)获取令牌,把它放在Authorization: Bearer头里调用API,返回401未授权,提示信息是Invalid username or password. - 从ThingsBoard Web界面(Keycloak登录后)提取的JWT令牌却能正常调用API,说明两种令牌的格式或声明存在差异。
参考令牌请求命令:
curl -X POST "https://keycloak.iuoc-int.ch/realms/iuoc/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=password" \ -d "client_id=<CLIENT ID>" \ -d 'scope=openid email profile' \ -d "username=<USER>" \ -d "password=<PWS>" \ -d "client_secret=<CLIENT SECRET>"
关键配置调整
1. Keycloak客户端配置
得让Access Token包含ThingsBoard需要的声明
ThingsBoard默认认JWT里的sub(用户唯一标识)、username或email这些声明,还会检查令牌的受众(aud)是否匹配。- 进入Keycloak对应客户端的Mappers页面,添加必要的声明映射:
- 如果ThingsBoard靠
username识别用户,就加个User Property类型的映射,属性名填username,Token Claim Name也填username,勾选Add to access token。 - 确认
sub声明默认已经存在(Keycloak一般会自动添加)。
- 如果ThingsBoard靠
- 检查客户端的Access Settings:
- 密码授权类型必须开启
Direct Access Grants Enabled,别漏掉。 - 测试环境下
Valid Redirect URIs可以填*,生产环境记得限制范围。
- 密码授权类型必须开启
- 进入Keycloak对应客户端的Mappers页面,添加必要的声明映射:
校验令牌的受众(aud)
ThingsBoard会检查令牌的受众是否匹配自己配置的客户端ID。如果请求令牌用的client_id和ThingsBoard集成时用的不是同一个,肯定会认证失败。- 保证请求令牌的
client_id和ThingsBoard里配置的Keycloak客户端ID完全一致。 - 如果需要多个客户端共用令牌,就在Keycloak客户端的Mappers里加个
Audience映射,把ThingsBoard的客户端ID加到aud声明里。
- 保证请求令牌的
2. ThingsBoard配置
调整JWT认证的验证规则
修改ThingsBoard的application.yml(或环境变量),让JWT验证逻辑适配Keycloak返回的令牌:- 检查
security.jwt相关配置:security: jwt: enabled: true use-x509-certificate: false secret: ${JWT_SECRET:YOUR_SECRET} token-validity-in-seconds: 3600 authority-prefix: ROLE_ # 填写Keycloak对应Realm的公钥,从Keycloak Realm的Keys页面获取 public-key: | -----BEGIN PUBLIC KEY----- YOUR_KEYCLOAK_PUBLIC_KEY -----END PUBLIC KEY----- # 把Keycloak的客户端ID加到允许的受众列表 audience: YOUR_THINGSBOARD_CLIENT_ID - 公钥一定要填对,否则签名验证会失败。
- 检查
开启密码授权类型的令牌支持
ThingsBoard默认可能对密码授权获取的令牌有额外校验,得确认开启了该授权类型的支持:- 在
security.yml或application.yml的oauth2配置中,确保指向Keycloak,并且包含password授权类型:security: oauth2: enabled: true registration: keycloak: client-id: YOUR_CLIENT_ID client-secret: YOUR_CLIENT_SECRET scope: openid,email,profile authorization-grant-type: password,authorization_code provider: keycloak: issuer-uri: https://<keycloak url>/realms/iuoc user-name-attribute: username # 也可以填email,看ThingsBoard认哪个字段当用户名
- 在
3. 对比令牌内容找差异
用jwt.io这类工具解析两种令牌,重点对比以下几点:
aud(受众)里是否包含ThingsBoard的客户端ID。username或email声明是否存在且正确。iss(发行方)和ThingsBoard配置的issuer-uri是否一致。- 令牌的签名算法和ThingsBoard配置的公钥是否匹配。
内容的提问来源于stack exchange,提问作者Jean-Pierre Miceli
相关产品推荐
相关产品推荐

