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

如何在Vaadin+Spring项目中获取Keycloak的Access Token调用FastAPI?

Vaadin + Keycloak 获取Access Token调用FastAPI解决方案

问题背景

已基于Spring Security实现Vaadin应用通过Keycloak登录,能获取OidcUser对象,但仅能访问ID Token,需要获取Access Token调用后端FastAPI,同时确认现有认证流程是否正确。

现有认证流程理解:

  1. 用户尝试登录Vaadin UI
  2. 重定向至Keycloak指定Realm完成认证
  3. 认证成功后用户登录Vaadin应用
  4. 应用使用用户的Access Token调用FastAPI加载数据
  5. FastAPI验证Token有效性后返回用户对应租户的数据

流程正确性确认

你的流程完全正确,符合OAuth2授权码流的标准逻辑。需要明确的是:OidcUser本身不直接存储Access Token,但Spring Security会将Access Token与当前用户的认证信息绑定,可通过Spring提供的工具类获取。

获取Access Token的实现方法

1. 注入OAuth2AuthorizedClientService获取Token

Spring Security的OAuth2AuthorizedClientService可加载当前用户的授权客户端信息,其中包含有效的Access Token。

示例服务类:

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

@Service
public class FastApiClient {

    private final OAuth2AuthorizedClientService authorizedClientService;
    private final WebClient webClient;

    public FastApiClient(OAuth2AuthorizedClientService authorizedClientService) {
        this.authorizedClientService = authorizedClientService;
        this.webClient = WebClient.create("http://your-fastapi-base-url");
    }

    public String fetchUserData(@AuthenticationPrincipal OidcUser currentUser) {
        // 加载Keycloak授权客户端,clientId需与配置文件中的一致
        OAuth2AuthorizedClient authorizedClient = authorizedClientService.loadAuthorizedClient(
                "keycloak", currentUser.getName());
        
        // 获取Access Token字符串
        String accessToken = authorizedClient.getAccessToken().getTokenValue();
        
        // 调用FastAPI,携带Bearer Token请求头
        return webClient.get()
                .uri("/api/user/data")
                .headers(headers -> headers.setBearerAuth(accessToken))
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }
}

2. 配置OAuth2客户端参数

确保application.properties中配置正确的Keycloak客户端信息,尤其是scope需包含FastAPI所需的权限范围:

# Keycloak客户端配置
spring.security.oauth2.client.registration.keycloak.client-id=vaadin-app-client
spring.security.oauth2.client.registration.keycloak.client-secret=your-client-secret
spring.security.oauth2.client.registration.keycloak.scope=openid,profile,api-access # api-access为FastAPI对应的scope
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://your-keycloak-domain/realms/your-realm-name

3. 在Vaadin View中调用API

在Vaadin视图中注入服务类,获取当前用户并调用FastAPI:

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.router.Route;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;

@Route("user-dashboard")
public class UserDashboardView extends VerticalLayout {

    private final FastApiClient fastApiClient;

    public UserDashboardView(FastApiClient fastApiClient) {
        this.fastApiClient = fastApiClient;
        
        TextArea resultArea = new TextArea("API返回数据");
        Button fetchButton = new Button("获取我的数据", event -> {
            OidcUser currentUser = getCurrentUser();
            String apiResult = fastApiClient.fetchUserData(currentUser);
            resultArea.setValue(apiResult);
        });
        
        add(fetchButton, resultArea);
    }

    private OidcUser getCurrentUser() {
        return (OidcUser) getUI().get().getSession().getAttribute("SPRING_SECURITY_CONTEXT")
                .getAuthentication().getPrincipal();
    }
}

关键注意事项

  • Token自动刷新:Spring Security会自动处理Access Token的过期刷新(前提是Keycloak颁发了Refresh Token),OAuth2AuthorizedClientService返回的始终是有效Token。
  • FastAPI Token验证:FastAPI需配置Keycloak的JWKS端点({keycloak-issuer-uri}/protocol/openid-connect/certs)来验证Token的签名和有效性,同时解析Token中的角色/scope声明实现权限控制。
  • Scope权限匹配:确保Keycloak客户端配置的scope与FastAPI要求的一致,否则Access Token会缺少必要的权限声明,导致API调用被拒绝。

内容的提问来源于stack exchange,提问作者Loahrs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 13:43:22