如何解决使用 Keycloak Script Mapper 聚合声明中角色的属性
我们有一个 Keycloak 脚本映射器来将角色的属性添加到 ID 令牌。目标是聚合角色属性中可用的值。映射器看起来像这样:
/**
* Merge with concatenation for the values of attributes obtained
* from the token with the attributes obtained from the roles. If for
* example a group and a role have the same attribute key,the values
* for that key from the group and role will be concatenated.
*
* KNown limitations:
* When only roles have a certain attribute,and not a group,the
* mapper only uses the first role it can find. Bug was difficult to
* fix because state in the variable currentClaims seems to be
* persisted over multiple calls.
* Workaround: Also add this specific attribute to a group with a
* dummy value.
*
* NOTE: there is no role attribute mapper out-of-the-Box in
* Keycloak.
*
* Available variables in script:
* user - the current user
* realm - the current realm
* token - the current token
* userSession - the current userSession
* keycloakSession - the current keycloakSession
*
* Documentation on available variables:
* https://stackoverflow.com/a/52984849
*/
var currentClaims = {};
token.getotherClaims().forEach(function(k,v) {
currentClaims[k] = v;
});
function isMultiValued(v) {
// From experience,multivalued attribute values are sometimes
// Arrays and sometimes Objects. Thus look for negative case:
// anything other than a string is multivalued.
return !(typeof v === 'string' || v instanceof String);
}
function addToList(l,values) {
for each(var v in values) {
l.add(v);
}
return l;
}
function toStringArray(arr) {
return Java.to(arr,"java.lang.String[]");
}
user.getRealmRoleMappings().forEach(function(roleModel) {
roleModel.getAttributes().forEach(function(k,v) {
var currentValue = currentClaims[k];
if (k in currentClaims) {
if (!isMultiValued(currentValue)) {
v = toStringArray([currentValue].concat(v));
} else {
v = addToList(currentValue,v);
}
}
currentClaims[k] = v; // <= to also aggregate over roles!
token.setotherClaims(k,v);
});
});
我添加的带有 currentClaims[k] = v
的部分是为了聚合角色中可用的值,因此如果两个角色包含相同的属性,它们的值也会聚合。
例如,如果我们有一个用户具有角色 a 和 b,分别具有值为 1 和 2 的属性 foo,我们期望 ID 令牌包含对值为 1 和 2 的 foo 的声明。
user:
role a foo -> 1
role b foo -> 2
expected ID token:
foo -> [1,2]
但是使用当前代码,currentClaims
变量似乎在多次调用函数时保持状态。每次检查 ID 令牌时,都会将 2
的更多值添加到令牌中,导致每次检索令牌时都会添加越来越多的 [1,2,...,2]
声明,例如 2
。我尝试将整个调用包装在一个函数中,以便可能在调用之间丢弃状态,但无济于事。结果如下:
为什么状态会保存在多个调用中?有没有办法同时聚合角色属性的值?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。