java Keycloak从用户存储SPI发布具有过时自定义属性的JWT令牌

njthzxwz  于 2023-06-20  发布在  Java
关注(0)|答案(1)|浏览(122)

我使用Keycloak版本19.0.1和自定义用户存储SPI从现有的遗留数据库加载用户。我通过提到的用户存储SPI向Keycloak用户表示模型添加了一些自定义属性。这些自定义属性是Keycloak在调用/token端点时发出的JWT令牌的一部分。
当调用/token端点时,Keycloak会按预期使用自定义属性发出JWT令牌。然而,当遗留数据库中的用户从遗留应用程序更新时,keycloak仍然会发出具有过时自定义属性值的JWT令牌。我相信这是Keycloak中的缓存问题,但无法找到正确的缓存选项来禁用缓存,并始终为发布的JWT令牌获取最新的自定义属性值。Keycloak似乎默认支持各种不同的本地和分布式缓存,可以使用XML文件进行配置:

我使用默认的缓存模式,根据文档是Infinispan。到目前为止,我已经尝试了以下方法(见下面的docker图像):

  • 构建keycloak时传递kc.sh build --spi-user-cache-infinispan-enabled=false选项
  • 在构建阶段传递环境变量KC_SPI_USER_CACHE_DEFAULT_ENABLED=false
  • 设置NO_CACHE政策上的用户fedaration,但似乎有一个大的和自定义属性与此选项在Keycloak 19版本失踪:https://github.com/keycloak/keycloak/issues/10826(因此现在对我来说不是一个选择)

我应该使用什么缓存配置来始终获取Keycloak颁发的JWT令牌中的最新自定义属性?我应该通过传递XML文件来自定义Infinispan配置吗?应该准确更改哪个缓存配置?

    • 注意**:一个有帮助的手动解决方法是在Keycloak中使用户的所有用户会话无效。之后,keycloak总是发出具有最新自定义属性的JWT令牌。
FROM <private-/gradle:7.1.0-jdk11 AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
RUN gradle build --no-daemon

FROM <private-registry>/quay.io_keycloak/keycloak:19.0.1 as builder

ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true
ENV KC_DB=postgres
ENV KC_HTTP_RELATIVE_PATH="/auth"

ENV KC_HTTP_ENABLED=true
ENV KC_HOSTNAME_STRICT_HTTPS=false
ENV KC_HOSTNAME_STRICT=false
ENV KC_TRANSACTION_XA_ENABLED=false
ENV KC_SPI_USER_CACHE_DEFAULT_ENABLED=false

COPY --from=build /home/gradle/src/user-storage-spi/build/libs/*.jar /opt/keycloak/providers/
COPY /conf/quarkus.properties /opt/keycloak/conf/quarkus.properties

RUN /opt/keycloak/bin/kc.sh build --spi-user-cache-infinispan-enabled=false

FROM <private-registry>/quay.io_keycloak/keycloak:19.0.1
COPY --from=builder /opt/keycloak/ /opt/keycloak/
WORKDIR /opt/keycloak

ENV KC_HTTP_ENABLED=true
ENV KC_HOSTNAME_STRICT_HTTPS=false
ENV KC_HOSTNAME_STRICT=false
ENV KC_TRANSACTION_XA_ENABLED=false
ENV KC_SPI_USER_CACHE_DEFAULT_ENABLED=false

ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
t2a7ltrp

t2a7ltrp1#

由于凭证输入验证总是在您实现的UserStorageProvider中执行,因此您可以使用KeycloakSession对象简单地使被覆盖的isValid()方法中的用户无效:

public MyUserStorageProvider(KeycloakSession session, ComponentModel model) {
    this.session = session;
    this.model = model;
}

 @Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput credentialInput) {
    // invalidate user in cache here to ensure that custom user attributes are refreshed on every new request
    session.invalidate(InvalidationHandler.ObjectType.USER, user.getId());

    ...
}

相关问题