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

Hashicorp Vault作OIDC Provider时令牌权限不足问题求助

问题描述

我正尝试将Hashicorp Vault用作OIDC Provider,基于Spring Boot开发REST应用并通过Postman测试OAuth2授权(学习场景,尽量遵循生产最佳实践),遇到权限校验不生效的问题:令牌无scope信息,高权限接口返回403,低权限接口实际走兜底认证规则而非权限校验。

Spring Boot配置

应用部署于https://dev.home.my.net:9780/

POM依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-vault-config</artifactId>
    <version>4.0.1</version>
</dependency>

application.yml配置

spring:
   security:
        oauth2:
            resourceserver:
                jwt:
                    issuer-uri: https://utils.home.my.net:9790/v1/identity/oidc/provider/dummyapi-provider

SecurityFilterChain配置

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.cors().and().csrf().disable();

    http.authorizeHttpRequests((authz) -> authz
            .requestMatchers(ELEVATED_WHITELIST).hasAnyAuthority("SCOPE_MYADMIN", "SCOPE_MYELEVATED")
            .requestMatchers(WHITELIST).hasAnyAuthority("SCOPE_MYADMIN", "SCOPE_MYELEVATED", "SCOPE_MYUSER")
            .requestMatchers(OPEN_ACCESS).permitAll()
            .requestMatchers("/**").authenticated()
        );
        http.oauth2ResourceServer().jwt();

    return http.build();
}
  • ELEVATED_WHITELIST:仅允许MYADMIN和MYELEVATED权限访问的请求映射列表
  • WHITELIST:允许MYADMIN、MYELEVATED和MYUSER权限访问的请求映射列表
  • OPEN_ACCESS:允许所有访问的非上述列表端点

Hashicorp Vault配置

已完成以下配置步骤:

  1. 启用userpass认证方式
  2. 在userpass下创建用户my_admin_user
  3. 创建同名实体my_admin_user,关联上述userpass用户
  4. 创建MYADMIN组
  5. 将my_admin_user加入MYADMIN组
  6. 在OIDC Provider下创建dummyapi应用,获取Client ID和Client Secret
  7. 创建MYADMIN分配,关联my_admin_user用户和MYADMIN组
  8. 创建MYADMIN scope,配置如下JSON:
{
  "username": {{identity.entity.name}},
  "groups": {{identity.entity.groups.names}}
}
  1. 创建dummyapi-provider,并在Supported scopes中选择上述MYADMIN scope

Postman测试配置

两个请求的OAuth2配置一致:

Authorization Type: Oauth 2.0
Callback URL: https://dev.home.my.net:9780/
Auth Url: https://utils.home.my.net:9790/ui/vault/identity/oidc/provider/dummyapi-provider/authorize
Access Token Url: https://utils.home.my.net:9790/v1/identity/oidc/provider/dummyapi-provider/token
Client ID: 从Vault Applications->dummyapi复制
Client Secret: 从Vault Applications->dummyapi复制
Scope: **openid** (曾看到需配置openid,但Azure测试时可配置其他scope并被SecurityFilterChain识别)

测试结果

  • 第一个GET请求:访问https://dev.home.my.net:9780/dummyapi/listItems(属于WHITELIST),使用返回的ID Token可正常获取200 OK响应,但实际是通过.requestMatchers("/**").authenticated()规则放行,而非WHITELIST的权限校验。
  • 第二个GET请求:访问https://dev.home.my.net:9780/dummyapi/listPrivateItems(属于ELEVATED_WHITELIST),认证成功但返回403 Forbidden,响应头包含:
WWW-Authenticate: Bearer error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token.", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"

补充信息

  • ID Token payload(jwt.io提示签名无效):
{
  "at_hash": "3Rz7cznliUSLrB2St7RS5g",
  "aud": "6Am2NXPeM8J6DaV4sX0JMPUZBsH32L78",
  "c_hash": "Tc9d3_evG3diE2YGXtCGSg",
  "exp": 1683955132,
  "iat": 1683868732,
  "iss": "https://utils.home.my.net:9790/v1/identity/oidc/provider/dummyapi-provider",
  "namespace": "root",
  "sub": "25328fea-cc19-f517-83f8-5eee3bbaf5e0"
}
  • Access Token为二进制格式,jwt.io无法解析且提示签名无效

求助:如何在Postman、Hashicorp Vault或Spring Boot的SecurityFilterChain中进行配置,使令牌包含对应scope,实现不同权限用户访问对应资源?


解决方案

一、Vault端配置修正

1. 完善Scope与分配的绑定

  • 检查MYADMIN分配配置:确保分配不仅关联用户和组,还明确指定包含MYADMIN scope。Vault的OIDC分配需要显式绑定scope,否则用户认证后令牌不会携带对应scope字段。
  • 按需创建MYELEVATED、MYUSER scope,配置可复用现有格式:
{
  "username": {{identity.entity.name}},
  "groups": {{identity.entity.groups.names}}
}
  • 在dummyapi-provider的Supported scopes中,添加openid、MYADMIN、MYELEVATED、MYUSER所有需要的scope。

2. 切换Access Token为JWT格式

Vault默认OIDC Access Token是不透明二进制令牌,需修改Provider配置:

  • 编辑dummyapi-provider,找到Access Token Format选项,选择jwt而非默认的opaque。生成的JWT格式令牌会包含scope、用户组等可解析的权限信息。

3. 验证JWKS端点可用性

确认https://utils.home.my.net:9790/v1/identity/oidc/provider/dummyapi-provider/.well-known/openid-configuration及对应JWKS端点可正常访问,确保Spring Boot能获取公钥校验令牌签名。

二、Postman配置调整

1. 请求正确的Scope组合

在OAuth2配置的Scope字段中,不要仅填openid,需明确请求用户对应的scope,比如openid MYADMIN(针对my_admin_user)、openid MYUSER(针对普通用户),这样Vault会在令牌中注入对应scope字段。

2. 使用Access Token发起请求

ID Token仅用于身份认证,资源访问需使用返回的Access Token作为Bearer令牌。Postman默认可能优先使用ID Token,需手动切换为Access Token,或在OAuth2配置中确保请求资源访问令牌。

三、Spring Boot配置优化

1. 补充OAuth2资源服务器依赖

当前仅引入spring-cloud-starter-vault-config(用于配置中心),需补充OAuth2资源服务器核心依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

2. 配置JWT权限转换器(可选)

如果需要将令牌中的scope或组信息转换为Spring Security权限,可添加如下配置:

@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
    JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
    // 从scope字段生成带SCOPE_前缀的权限
    grantedAuthoritiesConverter.setAuthorityPrefix("SCOPE_");
    grantedAuthoritiesConverter.setScopeAttributeName("scope");

    JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
    converter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
    return converter;
}

并在SecurityFilterChain中关联:

http.oauth2ResourceServer()
    .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()));

3. 优化权限规则写法

将兜底规则requestMatchers("/**").authenticated()替换为更规范的anyRequest().authenticated(),规则顺序保持不变(具体规则优先于兜底规则):

http.authorizeHttpRequests((authz) -> authz
        .requestMatchers(ELEVATED_WHITELIST).hasAnyAuthority("SCOPE_MYADMIN", "SCOPE_MYELEVATED")
        .requestMatchers(WHITELIST).hasAnyAuthority("SCOPE_MYADMIN", "SCOPE_MYELEVATED", "SCOPE_MYUSER")
        .requestMatchers(OPEN_ACCESS).permitAll()
        .anyRequest().authenticated()
    );

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:37:00