Keycloak公钥非base64url编码致jwt.io校验JWT失败解决方法
问题根因
触发校验报错、Header和Payload板块空白的核心原因有两个:
- 未将完整的三段式JWT字符串粘贴到校验工具的编码内容输入区,工具无法解析到合法的base64url编码JWT结构,自然无法填充对应板块内容,同时抛出编码错误
- 直接从Realm设置页复制的公钥为裸公钥参数,并非标准PEM格式,无法被校验工具直接识别用于验签
正确操作流程
1. 从Keycloak获取合规验签公钥
- 进入目标Realm的设置页面,打开「Keys」标签页
- 在活动密钥列表中,找到签名算法和你使用的算法一致(通常为RS256)的密钥条目,复制对应条目的公钥内容,同时记录该条目的
kid(密钥ID),后续生成JWT需要用到 - 将复制到的公钥内容手动拼接为标准PEM格式,格式如下:
-----BEGIN PUBLIC KEY----- <粘贴你复制到的公钥内容,删除所有多余空格、换行,保证内容连续> -----END PUBLIC KEY-----
注意:不要直接复制Realm常规设置页展示的公钥,该位置公钥容易出现字符缺失、格式错乱问题,优先从Keys标签页对应密钥条目复制
2. 生成符合client_assertion规范的JWT
用于Keycloak客户端认证的client_assertion类型JWT,必须满足以下结构要求,否则会被Keycloak拒绝:
- Header必填字段:
alg:填写签名使用的算法,必须和Keycloak客户端配置的认证算法、你选的验签公钥算法一致,通常为RS256typ:固定值为JWTkid:填写第一步记录的对应Keycloak密钥ID,必须完全匹配
- Payload必填字段:
iss:填写当前客户端的Client IDsub:和iss取值一致,填写当前客户端的Client IDaud:填写Keycloak对应Realm的token端点地址jti:全局唯一的随机字符串,用于防重放攻击exp:JWT过期时间的Unix时间戳,建议设置为签发后1-5分钟,不要设置过长有效期
- 签名规则:先将Header、Payload分别做base64url编码,用英文点号拼接得到待签名字符串,再用客户端持有的私钥对待签名字符串做签名,签名结果同样做base64url编码,拼接在待签名字符串末尾,最终得到
header.payload.signature格式的完整JWT字符串
3. 校验JWT的正确操作
- 先将生成的完整三段式JWT字符串粘贴到校验工具的Encoded输入区,此时工具会自动解析填充Header、Payload板块内容,不会再报base64url编码错误
- 在校验工具的验签密钥输入区,替换为第一步拼接好的PEM格式公钥,工具自动完成验签后显示签名验证通过,即代表JWT格式符合规范
内容的提问来源于stack exchange,提问作者Kiran
相关产品推荐
相关产品推荐

