You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vaadin AccessAnnotationChecker无法读取JWT Token中Keycloak角色的问题

Vaadin Flow + Quarkus + Keycloak角色权限校验问题

环境

  • Vaadin Flow 23.2.4
  • Quarkus 2.13.2.Final
  • Keycloak 16.1.1

问题描述

Keycloak定义的角色已存在于JWT Token的realm_access.roles中,但Vaadin的AccessAnnotationChecker无法通过请求获取这些角色。需求是直接使用AccessAnnotationChecker而非自定义校验器,且同类Spring Boot+Spring Security应用中该组件可正常工作。

现有实现与现象

BootstrapCustomizer代码实现

AccessAnnotationChecker accessAnnotationChecker = new AccessAnnotationChecker();

void onServiceInit(@Observes ServiceInitEvent event) {
    event.getSource().addUIInitListener(uiEvent -> {
        final UI ui = uiEvent.getUI();
        ui.addBeforeEnterListener(this::beforeEnter);
    });
}

private void beforeEnter(BeforeEnterEvent event) {
    accessToken.getClaimNames().stream().forEach(n -> System.out.println(n + ":" + accessToken.getClaim(n).toString()));

    System.out.println("is user in role user:" + ((HttpServletRequest)VaadinServletRequest.getCurrent()).isUserInRole("user"));
    if (!accessAnnotationChecker.hasAccess(event.getNavigationTarget())) {
        System.out.println("REROUTING ON ACCESS DENIED");
        event.rerouteTo(FlightView.class);
    }
}

Token角色打印结果

控制台输出显示Token包含目标角色:

realm_access:{"roles":["privileged","default-roles-xxx","User","offline_access","uma_authorization","user"]}

视图权限注解与菜单控制

Vaadin视图使用@RolesAllowed注解声明权限:

@RolesAllowed({"user","privileged"})
public class ProfileView extends VerticalLayout {
    // 视图逻辑实现
}

通过AccessAnnotationChecker控制菜单显示:

if (accessAnnotationChecker.hasAccess(ProfileView.class))
    navbarTabs.add(new NavTab("Profile", ProfileView.class));

应用配置

quarkus.oidc.client-id=my-client
quarkus.oidc.auth-server-url=https://xy.zzy.no/auth/realms/xxx
quarkus.oidc.credentials.secret=secret
quarkus.oidc.tls.verification=none
quarkus.oidc.authentication.user-info-required=false

# this must be false with type=web-app, but probably is needed for roles check?
# this only works for service-applicatoins, see https://quarkus.io/guides/security-openid-connect-web-authentication instead
quarkus.keycloak.policy-enforcer.enable=false
# this is needed when backend is not https
quarkus.oidc.authentication.force-redirect-https-scheme=false
quarkus.oidc.application-type=web_app

quarkus.http.auth.permission.authenticated.paths=/*
quarkus.http.auth.permission.authenticated.policy=authenticated

quarkus.oidc.logout.path=/logout
quarkus.oidc.logout.post-logout-path=/

用户疑问

曾尝试考虑启用quarkus.keycloak.policy-enforcer.enable=true,但该配置仅适用于服务应用,不适用于当前Web应用场景。

解决方案

问题根源是Quarkus Web应用模式下,默认未将Keycloak Token中的realm_access.roles映射为Java EE标准的安全角色,而AccessAnnotationChecker依赖该安全上下文进行权限判断。

1. 添加角色映射配置

在application.properties中添加以下配置,指定从Token的realm_access.roles字段读取角色:

quarkus.oidc.roles.role-claim-path=realm_access.roles

2. 验证安全上下文

配置完成后重启应用,检查((HttpServletRequest)VaadinServletRequest.getCurrent()).isUserInRole("user")是否返回true。若返回true,说明角色已成功映射到安全上下文,AccessAnnotationChecker即可正常识别@RolesAllowed注解的权限。

3. 注意事项

  • quarkus.keycloak.policy-enforcer仅用于API服务的权限强制,Web应用无需启用。
  • 确保quarkus.oidc.application-type=web_app配置正确,该模式适配Web UI的认证流程。

内容的提问来源于stack exchange,提问作者jon martin solaas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 08:35:24