Files
llm-wiki/raw/official-docs/spring-security-nested-authorities-claim-issue-15201.md
T

11 KiB

title, source_type, url, archive_url, related_branches, related_projects, tags, created
title source_type url archive_url related_branches related_projects tags created
official-doc / Spring Security GitHub Issue official-doc https://github.com/spring-projects/spring-security/issues/15201
feature-keycloak-spring-rs-role-mapping
keycloak-patterns
official-doc
keycloak-patterns
auth
spring-security
keycloak
jwt-validation
2026-07-18

official-doc / Spring Security GitHub Issue #15201 — Nested JWT Authorities Claim Support

Layer: raw/ — 외부 자료(공식 문서 / 대기업 기술 블로그)의 원문 발췌·출처 기록.

source_type 허용값

official-doc — Spring Security 프로젝트 자체 저장소(spring-projects/spring-security)의 GitHub Issue tracker. 이슈 등록자는 커뮤니티 contributor(thomasdarimont)이지만, 이슈가 vendor 공식 저장소에 등재되어 type: enhancement 라벨 + 6.4.x milestone 을 부여받았고, 해결 PR(#15202)이 Spring Security core maintainer jzheaux 에 의해 직접 머지됨 — vendor 가 문제와 해결책을 공식적으로 승인한 근거로 사용 가능.

Parent / 활용 branch (필수, 최소 1개+)

Branch 이 자료가 정당화하는 결정
raw/branch-notes/feature-keycloak-spring-rs-role-mapping Keycloak 의 nested claim realm_access.rolesJwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("realm_access.roles") 만으로 매핑할 수 없다는 known-limitation 확인 + custom Converter<Jwt, Collection<GrantedAuthority>> (또는 Spring Security 6.4+ ExpressionJwtGrantedAuthoritiesConverter) 가 필요하다는 vendor-side 근거

출처 / Source

  • 원본 URL: https://github.com/spring-projects/spring-security/issues/15201
  • 아카이브 URL: (미제공)
  • 저자 / 조직: 이슈 등록 — thomasdarimont (community contributor, author_association: CONTRIBUTOR) · 이슈 assignee / PR merge — jzheaux (Spring Security core maintainer) · 저장소 — spring-projects/spring-security (vendor 공식)
  • 발행일: 2024-06-04 (이슈 생성) / PR #15202 머지: 2024-09-24 / milestone 6.4.0-RC1
  • 마지막 확인일: 2026-07-18

왜 저장했는지 / Why archived

feature-keycloak-spring-rs-role-mapping branch 는 Keycloak realm_access.roles (nested claim) 를 Spring Authority 로 매핑하는 결정을 내렸으나(D4), 해당 branch-note 의 Claims To Verify 에 "JwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("realm_access.roles") 가 nested JSON path 를 정확히 파싱하는지" 가 planned/미검증 상태로 남아 있었다. 본 GitHub 이슈는 이 우려가 Spring Security 팀 스스로도 인지한 실제 known limitation 이었고, custom converter 워크어라운드와 ExpressionJwtGrantedAuthoritiesConverter(6.4+) 도입으로 해결되었음을 vendor 저장소 상에서 직접 확인시켜준다.

핵심 인용 / Key quotes (verbatim, 5문장)

[Issue #15201 title] "Support extracting nested authorities in JwtGrantedAuthoritiesConverter"

[Issue #15201 body — Current Behavior] "Currently custom code (custom JwtGrantedAuthoritiesConverter implementation) is required to extract the role "teacher" from the nested JWT claim shown below."

[Issue #15201 body — Expected Behavior] "Users should be able to specify a SpEL expression on the JwtGrantedAuthoritiesConverter to extract the granted authorities from a nested claim structure. This helps to reduce the necessary code to extract roles from nested structures in JWT access tokens generated by Keycloak and other OAuth2 authorization servers which expose roles in nested claims."

[Issue #15201 body — Context] "The Keycloak OAuth2 Authorization Server / OpenID Provider generates JWT access_tokens which contain deeply nested roles configuration like the following:" (이어지는 예시 JSON 에 "realm_access": { "roles": ["teacher"] } 포함)

[PR #15202 title, Fixes #15201, merged by jzheaux, milestone 6.4.0-RC1] "GH-15201 Introduce ExpressionJwtGrantedAuthoritiesConverter to extract nested authorities via SpEL expression"

Claims Extracted / 추출된 주장

Claim ID Claim (이 자료가 직접 말하는 것) Evidence quote Strength Applies to Does not prove
SS-15201-C1 "nested authorities 추출 지원" 은 Spring Security 공식 저장소에 type: enhancement 이슈로 등재되고 6.4.x milestone 에 배정된 인지된 gap 이다 (assignee: core maintainer jzheaux) [title] "Support extracting nested authorities in JwtGrantedAuthoritiesConverter" official-vendor-doc Spring Security 6.4 이전 버전에서 nested claim 자동 추출 미지원이라는 사실 확인 6.4 이전 모든 마이너 버전에서 정확히 동일하게 동작함을 개별 버전별로 증명하지는 않음
SS-15201-C2 이슈 등록 시점(Spring Security 6.4 이전) 기준, nested JWT claim 에서 role 을 추출하려면 custom JwtGrantedAuthoritiesConverter 구현(즉 커스텀 코드)이 필요했다 [Current Behavior] "Currently custom code (custom JwtGrantedAuthoritiesConverter implementation) is required to extract the role "teacher" from the nested JWT claim shown below." official-vendor-doc 커스텀 Converter<Jwt, Collection<GrantedAuthority>> 워크어라운드가 필요했다는 사실 근거 이 문장은 원 이슈 등록자(community contributor)가 작성한 "Current Behavior" 서술이며, Spring Security 팀이 별도 comment 로 "맞다" 라고 명시 확인한 문장은 아님 — 다만 이 정확한 전제를 해결하는 PR #15202 가 core maintainer 에 의해 머지되어 간접적으로 승인됨. setAuthoritiesClaimName("realm_access.roles") (내부적으로 top-level literal key lookup 이라서) 실패하는지 메커니즘은 본 이슈 텍스트에 직접 서술되지 않음
SS-15201-C3 Spring Security 는 이 문제를 해결하기 위해 ExpressionJwtGrantedAuthoritiesConverter 라는 새 클래스를 SpEL expression 기반으로 도입했고, 해당 PR(#15202)이 core maintainer jzheaux 에 의해 머지되어 milestone 6.4.0-RC1 에 포함되었다 [PR title, Fixes #15201] "GH-15201 Introduce ExpressionJwtGrantedAuthoritiesConverter to extract nested authorities via SpEL expression" official-vendor-doc ExpressionJwtGrantedAuthoritiesConverter 가 Spring Security 6.4.0-RC1 이상에서 존재/사용 가능하다는 근거 ExpressionJwtGrantedAuthoritiesConverter 의 정확한 API 사용법(Javadoc, 프로퍼티 이름 등)은 본 이슈/PR 메타데이터만으로 확정 안 됨 — 별도 reference doc 확인 필요
SS-15201-C4 Keycloak 이 발급하는 JWT access token 은 realm_access.roles 처럼 깊게 nested 된 role 구조를 갖는다 (이슈에 첨부된 예시) [Context] "The Keycloak OAuth2 Authorization Server / OpenID Provider generates JWT access_tokens which contain deeply nested roles configuration like the following:" + 예시 JSON realm_access.roles needs-confirmation Keycloak 토큰 구조에 대한 정성적 맥락 설명 이 서술은 커뮤니티 contributor 가 작성한 예시이며 Keycloak 공식 문서 자체는 아님 — Keycloak 자체의 realm_access claim 명세는 별도 Keycloak 공식 문서로 확인 필요

Usage Boundaries / 적용 경계

  • 이 자료가 직접 증명하는 것:
    • SS-15201-C1: nested claim(realm_access.roles 등) 자동 추출 미지원이 Spring Security 팀 스스로도 인지한 gap 이었다는 것 (vendor 저장소 등재 + core maintainer assignee + milestone 배정)
    • SS-15201-C2: 이슈 등록 시점 기준 workaround 로 custom JwtGrantedAuthoritiesConverter 구현이 필요했다는 것
    • SS-15201-C3: ExpressionJwtGrantedAuthoritiesConverter 가 이 문제의 공식 해결책으로 Spring Security 6.4.0-RC1 에 머지되었다는 것
  • 이 자료가 증명하지 않는 것:
    • JwtGrantedAuthoritiesConverter.setAuthoritiesClaimName()내부적으로 왜 (literal top-level key lookup 이라서) 점표기(dotted) nested path 를 파싱하지 못하는지 — 이 메커니즘 설명은 본 이슈 텍스트에 없음. 소스코드/Javadoc 확인 필요.
    • ExpressionJwtGrantedAuthoritiesConverter 의 정확한 설정 프로퍼티명·SpEL 문법 세부사항 (이슈 body 의 예시 spring.security.oauth2.resourceserver.jwt.authorities-claim-expression="[realm_access][roles]" 는 issue 제안 시점의 요청 문법이며, 실제 머지된 API 와 프로퍼티명이 동일하다는 보장은 본 자료만으로 없음 — 별도 reference doc/Javadoc 대조 필요)
    • 프로젝트의 실제 Spring Boot/Spring Security 버전이 6.4.0-RC1 이상인지 여부 (branch-note 의 TODO 는 Spring Boot 3.x 만 명시, 6.4 이상 pin 여부 미확정)
  • 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
    • feature-keycloak-spring-rs-role-mapping 에서 실제 사용할 Spring Boot/Spring Security 버전이 6.4 이상인지 확인 (미만이면 custom Converter<Jwt, Collection<GrantedAuthority>> 필수, 이상이면 ExpressionJwtGrantedAuthoritiesConverter 옵션 가능)
    • ExpressionJwtGrantedAuthoritiesConverter 실제 API 형태(생성자/SpEL 문법)는 Spring Security 6.4 공식 reference doc 또는 Javadoc 으로 별도 확인 후 코드 작성

메모 / Notes

  • 본 이슈는 GitHub REST API(api.github.com)로 직접 fetch — WebFetch 의 렌더링 요약본 대신 issue body/comments/연결 PR 의 raw JSON 필드를 그대로 저장해 self-grep 정합성을 높였다. 스크래치 파일: /tmp/claude-*/scratchpad/source-fetch-1784345524.txt (session-scoped, 영구 아님 — 인용은 본 파일에 보존됨).
  • 이슈 자체는 커뮤니티 contributor 가 작성했지만, PR 은 같은 contributor(thomasdarimont) 가 올렸고 core maintainer jzheaux 가 review 후 merge 했다는 점에서 vendor 승인으로 취급 가능 — 다만 "vendor 가 직접 작성한 설명문" 은 아니므로 Strength 표기 시 이 뉘앙스를 구분해 둠.
  • feature-keycloak-spring-rs-role-mapping 는 본 자료를 근거로 D6(매핑 메커니즘 = 수동 custom Converter, setAuthoritiesClaimName 폐기)를 신설해 이 nested-claim 한계를 결정으로 반영·확정했다(2026-07-18 /branch-spec). 다만 본 자료는 setAuthoritiesClaimName nested 를 실패하는지의 내부 메커니즘(literal top-level lookup)까지는 증명하지 않으며, custom converter 가 실제 token 에서 ROLE_* authority 를 방출하는지의 로컬 검증(그 branch §Claims To Verify + TODO)은 여전히 필요.