OidcProfileCreator处理TokenCredentials时未设置UserProfile ID问题咨询
我构建了一个基于OpenID Connect的直接Header客户端,代码如下:
OidcConfiguration config = new OidcConfiguration(); config.setClientId(clientId); config.setSecret(secret); config.setDiscoveryURI(discoveryUri); // additional settings of config OidcClient oidcClient = new OidcClient(config); OidcProfileCreator profileCreator = new OidcProfileCreator(config, oidcClient); HeaderClient client = new HeaderClient("my-custom-header", "my-custom-prefix", profileCreator);
令牌的认证/验证工作正常,但OidcProfileCreator从未在UserProfile中设置ID:仅使用OidcCredentials时会设置ID,使用TokenCredentials时则不会(参见OidcProfileCreator.java:118)。请问这是为什么?使用TokenCredentials时,UserProfile的ID难道不应该通过JWT的subject(sub)字段设置吗?
我期望生成的UserProfile能将JWS声明中的sub(主体)设置为org.pac4j.core.profile.UserProfile的ID。我使用的是pac4j 5.7.3版本,且当前版本的ProfileCreator行为与此一致。
核心原因
pac4j 5.7.3版本的OidcProfileCreator在处理TokenCredentials时,确实没有自动从JWT的sub字段提取并设置UserProfile的ID。这是因为该类的逻辑设计中,仅针对OidcCredentials做了ID赋值操作——OidcCredentials通常关联完整的OIDC授权流程,会携带用户身份的核心信息;而TokenCredentials更多被视为通用的令牌验证载体,默认流程里没有触发sub到profile ID的映射。
解决方案
你可以通过自定义OidcProfileCreator的子类,重写create方法来补充TokenCredentials场景下的ID设置逻辑:
public class CustomOidcProfileCreator extends OidcProfileCreator { public CustomOidcProfileCreator(OidcConfiguration configuration, OidcClient oidcClient) { super(configuration, oidcClient); } @Override public UserProfile create(Credentials credentials, WebContext context) { UserProfile profile = super.create(credentials, context); if (credentials instanceof TokenCredentials && profile != null) { TokenCredentials tokenCredentials = (TokenCredentials) credentials; // 从已验证的JWT中提取sub声明 JwtClaims claims = (JwtClaims) tokenCredentials.getCredentials(); if (claims != null && claims.getSubject() != null) { profile.setId(claims.getSubject()); } } return profile; } }
然后替换原代码中的OidcProfileCreator:
// 替换原创建逻辑 CustomOidcProfileCreator profileCreator = new CustomOidcProfileCreator(config, oidcClient); HeaderClient client = new HeaderClient("my-custom-header", "my-custom-prefix", profileCreator);
额外说明
如果不想自定义子类,也可以在获取到UserProfile后手动从TokenCredentials的JWT声明中提取sub并设置ID,但自定义ProfileCreator是更贴合pac4j流程的优雅方式。
内容的提问来源于stack exchange,提问作者orudicKS

