WSO2 APIM 4.2.0自定义JWT生成器:authorization_code授权时获取用户信息失败
问题场景
在WSO2 API Manager 4.2.0一体化部署环境中,使用自定义后端JWT生成器传递自定义声明customerId:
- 终端用户采用
client-credentials授权类型时功能正常 - 采用
authorization_code授权类型时,后端JWT生成失败,抛出**"User does not exist in the UserStore"**错误
调试确认:APIUtil.getClaims()执行失败的核心原因是jwtInfoDto.getEndUser()在authorization_code模式下返回用户的UUID(userId),而非用户名,导致无法在用户存储中匹配到目标用户。
根因分析
client-credentials授权:网关获取的endUser是客户端应用的标识(以用户名形式存储在用户库),因此APIUtil.getClaims()可正常查询声明authorization_code授权:默认情况下,网关从OAuth2令牌中获取的endUser是用户的UUID(userId),但APIUtil.getClaims()仅支持通过用户名查询用户存储,因此出现匹配失败
解决方案
修改自定义JWT生成器代码,先将userId转换为对应用户名,再调用APIUtil.getClaims()查询用户声明。修改后的完整代码如下:
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.osgi.service.component.annotations.Component; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.common.gateway.dto.JWTInfoDto; import org.wso2.carbon.apimgt.common.gateway.jwtgenerator.APIMgtGatewayJWTGeneratorImpl; import org.wso2.carbon.apimgt.common.gateway.jwtgenerator.AbstractAPIMgtGatewayJWTGenerator; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.user.api.UserStoreManager; import org.wso2.carbon.user.api.UserStoreException; import java.util.Map; import java.util.SortedMap; @Component( enabled = true, service = AbstractAPIMgtGatewayJWTGenerator.class, name = "CustomGatewayJWTGenerator" ) /** * Extend default JWT generator to add Customer ID as additional claim */ public class CustomGatewayJWTGenerator extends APIMgtGatewayJWTGeneratorImpl { private static final Log LOG = LogFactory.getLog(CustomGatewayJWTGenerator.class); @Override public Map<String, Object> populateCustomClaims(JWTInfoDto jwtInfoDto) { Map<String, Object> claims = super.populateCustomClaims(jwtInfoDto); SortedMap<String, String> userClaims; String customerIdClaimURI = "http://wso2.org/claims/customerId"; String endUser = jwtInfoDto.getEndUser(); int tenantId = jwtInfoDto.getEndUserTenantId(); try { // Convert userId to username for authorization_code flow UserStoreManager userStoreManager = APIUtil.getUserStoreManager(tenantId); String username = userStoreManager.getUserNameFromUserId(endUser); // Query claims with username userClaims = APIUtil.getClaims(username, tenantId, getDialectURI()); if (userClaims.containsKey(customerIdClaimURI)) { claims.put(customerIdClaimURI, userClaims.get(customerIdClaimURI)); } } catch (APIManagementException | UserStoreException e) { LOG.error("Error occurred when populating custom claims", e); } return claims; } }
可选配置优化
若希望网关直接返回用户名而非userId,可修改APIM的deployment.toml配置文件,添加以下内容:
[apim.oauth_config] enable_user_id_in_access_token = false
该配置会让OAuth2令牌存储用户名而非userId,jwtInfoDto.getEndUser()将直接返回用户名,无需代码转换。注意:该配置会影响所有依赖userId的功能,需根据业务场景评估后启用。
内容的提问来源于stack exchange,提问作者Isuru Hemantha
相关产品推荐
相关产品推荐

