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

如何通过Spring OIDC/OAuth2从AWS Cognito自定义声明获取权限角色

解决Spring Boot OAuth2/OIDC中Cognito用户角色映射问题

问题背景

在Spring Boot中完成基础OAuth2/OIDC认证配置后,认证功能运行稳定,但获取用户授权权限时仅能看到OIDC_USER这一个角色。已知Cognito返回的ID Token中包含cognito:groups自定义声明,其中存储了用户的角色列表(如USER、ADMIN等),希望直接将该声明中的角色映射为Spring Security的GrantedAuthority,且无需手动编写大量JWT/OAuth相关类,同时不破坏原有OIDC认证流程。

可行解决方案

方案:自定义OidcUserService(推荐,不破坏原有自动配置)

Spring Security OAuth2客户端默认使用OidcUserService处理OIDC用户信息,通过重写该类的loadUser方法,可以轻松从ID Token中提取cognito:groups并转换为权限,且无需修改安全过滤器链。

代码实现

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CustomOidcUserService extends OidcUserService {

    @Override
    public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
        // 调用父类方法获取默认OIDC用户信息
        OidcUser oidcUser = super.loadUser(userRequest);
        
        // 从ID Token中提取cognito:groups声明
        List<String> userGroups = oidcUser.getClaim("cognito:groups");
        
        // 将角色转换为Spring Security标准权限(添加ROLE_前缀符合规范)
        Collection<GrantedAuthority> groupAuthorities = userGroups.stream()
                .map(group -> new SimpleGrantedAuthority("ROLE_" + group))
                .collect(Collectors.toList());
        
        // 合并原有权限(如OIDC_USER)与新角色权限
        groupAuthorities.addAll(oidcUser.getAuthorities());
        
        // 返回包含完整权限的自定义OIDC用户对象
        return new DefaultOidcUser(groupAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());
    }
}

方案说明

  • 该类会被Spring Security自动识别并替换默认的OidcUserService,完全兼容原有OIDC认证流程
  • 自动保留原有OIDC_USER权限,同时添加cognito:groups中的角色(带ROLE_前缀,符合Spring Security权限命名规范)
  • 无需手动配置过滤器链或其他复杂Bean,仅需添加该Service类即可生效

验证

配置完成后,用户登录成功后,可通过以下代码获取完整权限集合:

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 输出权限列表,包含ROLE_USER、ROLE_ADMIN、OIDC_USER等
authentication.getAuthorities().forEach(auth -> System.out.println(auth.getAuthority()));

附:原配置文件与ID Token示例

原配置文件

spring.security.oauth2.client.registration.cognito.client-id=xxxxx
spring.security.oauth2.client.registration.cognito.client-secret=123xxxx
spring.security.oauth2.client.registration.cognito.redirect-uri=${app.url}/login/oauth2/code/cognito
#spring.security.oauth2.client.registration.cognito.redirect-uri=${app.url}/dashboard
spring.security.oauth2.client.registration.cognito.client-name=myclient

#spring.security.oauth2.client.registration.cognito.scope=openid+email+profile
spring.security.oauth2.client.registration.cognito.scope=openid
spring.security.oauth2.client.registration.cognito.authorization-grant-type=authorization_code

spring.security.oauth2.client.provider.cognito.user-name-attribute=email
spring.security.oauth2.client.provider.cognito.jwk-set-uri: https://cognito-idp.us-east-1.amazonaws.com/aaaaaaa/.well-known/jwks.json

spring.security.oauth2.client.provider.cognito.authorization-uri=https://bbbbbbbbbb.auth.us-east-1.amazoncognito.com/oauth2/authorize
spring.security.oauth2.client.provider.cognito.token-uri=https://bbbbbbbbb.auth.us-east-1.amazonaws.com/oauth2/token

ID Token示例

{ 
  "claims": { 
    "at_hash": "111111aaaaaabbbbbbbccccc", 
    "sub": "5a8417c7-7875-4ac5-9d7f-b0ffd1b3490f", 
    "cognito:groups": [ "USER", "DEVELOPER", "ADMIN", "CLIENT" ], 
    "birthdate": "01/01/1901", 
    "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_abc123", 
    "updated_at": { "seconds": 1675049091, "nanos": 0 }, 
    "auth_time": { "seconds": 1679280866, "nanos": 0 }, 
    "nickname": "First", 
    "exp": { "seconds": 1679367266, "nanos": 0 }, 
    "iat": { "seconds": 1679280866, "nanos": 0 }, 
    "jti": "4f53349b-0e78-4c84-ac21-dd69ad3c9ea4", 
    "email": "myuser@email.com", 
    "email_verified": true, 
    "address": { "formatted": "123 N Main St" }, 
    "profile": "firstName", 
    "phone_number_verified": true, 
    "cognito:username": "myuser", 
    "given_name": "First", 
    "nonce": "yyyyyyyyyyyyyyyyyyyyyyyy", 
    "picture": "https://vectorified.com/images/generic-avatar-icon-24.png", 
    "origin_jti": "8ae68e89-19b2-47a3-a2cb-34fb513ce9d0", 
    "aud": [ "1111aaaabbb" ], 
    "token_use": "id", 
    "name": "First Last", 
    "phone_number": "+11112221234", 
    "family_name": "Last" 
  }, 
  "tokenValue": "xxx...", 
  "issuedAt": { "seconds": 1679280866, "nanos": 0 }, 
  "expiresAt": { "seconds": 1679367266, "nanos": 0 } 
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:47:56