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配置
已完成以下配置步骤:
- 启用
userpass认证方式 - 在userpass下创建用户
my_admin_user - 创建同名实体
my_admin_user,关联上述userpass用户 - 创建
MYADMIN组 - 将
my_admin_user加入MYADMIN组 - 在OIDC Provider下创建
dummyapi应用,获取Client ID和Client Secret - 创建
MYADMIN分配,关联my_admin_user用户和MYADMIN组 - 创建
MYADMINscope,配置如下JSON:
{ "username": {{identity.entity.name}}, "groups": {{identity.entity.groups.names}} }
- 创建
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分配配置:确保分配不仅关联用户和组,还明确指定包含MYADMINscope。Vault的OIDC分配需要显式绑定scope,否则用户认证后令牌不会携带对应scope字段。 - 按需创建
MYELEVATED、MYUSERscope,配置可复用现有格式:
{ "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

