Apache反向代理mod_auth_openidc无法获取用户声明问题排查
问题描述
我在Apache反向代理中使用mod_auth_openidc组件,通过传统授权码流对接远程身份提供商进行OIDC认证。认证已成功完成,我也被正确重定向至应用,但mod_auth_openidc无法获取身份提供商发送的用户声明。在反向代理的调试日志中,看到如下错误信息:
oidc_util_decode_json_object: JSON parsing returned an error: '[' or '{' expected near 'eyJhbGciOiJSUzI'”日志中包含身份提供商发送的完整JWT令牌,我通过在线网站解码该签名令牌时,能正常验证签名和编码,并获取到声明。看起来auth_openidc模块未先解码令牌,而是直接将其当作纯JSON文本解析。
问题核心
这个错误的本质是mod_auth_openidc收到的用户声明数据格式不符合预期:它期望拿到纯JSON格式的用户信息,但身份提供商返回的是JWT格式的ID Token(或JWT格式的UserInfo响应),而模块配置没有正确识别这种格式,导致直接把JWT字符串当作JSON解析,触发语法错误。
修复步骤
1. 启用从ID Token提取用户声明
如果身份提供商已将用户声明嵌入ID Token中,直接开启从ID Token提取声明的配置,避免模块去调用UserInfo端点:
# 确保包含openid基础范围,按需添加其他范围 OIDCScope "openid profile email" # 开启从ID Token提取用户声明 OIDCUseInfoFromIdToken On
2. 适配JWT格式的UserInfo响应
如果你的配置依赖UserInfo端点获取声明,但身份提供商返回的是JWT格式的响应,需要指定签名算法让模块自动解码:
# 替换为身份提供商实际使用的签名算法(如RS256、HS256、ES256等) OIDCUserInfoTokenSignedResponseAlg RS256
3. 确认身份提供商元数据配置正确
确保模块能正确获取身份提供商的OIDC元数据,避免手动配置端点出错:
# 替换为你的身份提供商的OIDC元数据地址 OIDCProviderMetadataURL https://your-idp/.well-known/openid-configuration
如果手动配置端点,需保证OIDCUserInfoURL指向正确的UserInfo端点,且Apache能正常访问该端点。
4. 检查ID Token签名验证配置
如果ID Token签名验证失败,模块可能会跳过解析直接返回原始令牌,导致后续错误。确保配置了正确的公钥或JWKS地址:
# 方式1:使用JWKS地址(推荐) OIDCProviderJwksUri https://your-idp/jwks.json # 方式2:手动配置公钥 OIDCProviderPublicKey "-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... -----END PUBLIC KEY-----"
验证修复
修改配置后,重启Apache服务,重新发起OIDC认证流程,查看调试日志是否消除JSON解析错误,同时检查应用是否能正常获取用户声明。
内容的提问来源于stack exchange,提问作者ThierryC

