Split View: Keycloak 26.7 — SCIM 프리뷰 승격, 외부 Infinispan 없는 멀티클러스터 v2, 그리고 업그레이드에서 밟기 쉬운 것들
Keycloak 26.7 — SCIM 프리뷰 승격, 외부 Infinispan 없는 멀티클러스터 v2, 그리고 업그레이드에서 밟기 쉬운 것들
- 들어가며 — 분기마다 하나씩, 이번엔 26.7
- SCIM API — 4년 열려 있던 이슈가 코어로 (프리뷰)
- 멀티클러스터 v2 — 외부 Infinispan 없이 (프리뷰)
- Organizations — 멀티테넌시 위임이 현실적으로
- 업그레이드에서 밟기 쉬운 것들
- 폐기 레이더 — 지금 끄거나 갈아탈 것
- 그 밖의 표준 실험들 — 한 단락씩만
- 그래서 언제 올리고, 무엇을 켜나
- 마치며
- 참고 자료
들어가며 — 분기마다 하나씩, 이번엔 26.7
Keycloak은 요즘 석 달 간격으로 마이너를 냅니다. GitHub 릴리스 기준으로 26.5.0이 2026년 1월 6일, 26.6.0이 4월 8일, 그리고 26.7.0이 7월 9일에 나왔습니다. 마이너 하나가 나올 때마다 릴리스 노트만 훑고 넘어가기엔 이번 릴리스는 운영자 입장에서 걸리는 게 많습니다 — 오래 기다린 기능 둘(SCIM, 외부 캐시 없는 멀티클러스터)이 프리뷰로 올라왔고, 업그레이드 가이드의 breaking/notable 목록이 유난히 깁니다.
이 글은 공식 릴리스 노트와 저장소의 원문 adoc(릴리스 노트, 업그레이드 가이드), 그리고 기능 플래그의 실제 정의인 Profile.java를 대조해서 정리한 운영 관점 읽기입니다. Keycloak 26 아키텍처 자체가 처음이라면 Keycloak 26 아키텍처 딥다이브를 먼저 보는 편이 낫습니다.
SCIM API — 4년 열려 있던 이슈가 코어로 (프리뷰)
SCIM(System for Cross-domain Identity Management)은 사용자·그룹 같은 아이덴티티 리소스를 시스템 간에 표준 REST API로 읽고 쓰는 프로토콜입니다(스키마는 RFC 7643, 프로토콜은 RFC 7644). Okta나 Entra ID 같은 상용 IdP에서는 당연하게 여겨지는 기능인데, Keycloak 코어에는 없었습니다. 2022년 8월에 열린 SCIM 지원 이슈가 리액션 300개를 모으며 아직도 열려 있고, 그동안 이 공백은 scim-for-keycloak 같은 서드파티 확장이 메워 왔습니다.
이번에 그 공백이 코어에서 채워지기 시작했습니다. 타임라인을 코드로 확인하면 이렇습니다 — scim-api 기능 플래그는 26.6.0의 Profile.java에 experimental로 조용히 들어왔고(26.6.0 릴리스 노트에는 언급이 없습니다), 26.7.0에서 프리뷰로 승격됐습니다. 기본 비활성이라 --features=scim-api로 켜야 하고, 켠 뒤에도 realm 설정에서 realm별로 다시 토글해야 합니다.
구현 범위는 관리 가이드의 SCIM 장 기준으로 다음과 같습니다.
- 사용자·그룹의 생성/조회/수정/PATCH/삭제 전체와 그룹 멤버십 관리
- SCIM 필터 문법 전체와 페이지네이션
- Enterprise User 확장(RFC 7643 4.3절)과 User Profile 속성 매핑을 통한 커스텀 스키마 확장
- 스키마 디스커버리 엔드포인트
엔드포인트는 realm 단위로 열립니다.
/realms/<realm-name>/scim/v2/ServiceProviderConfig
/realms/<realm-name>/scim/v2/ResourceTypes
/realms/<realm-name>/scim/v2/Schemas
/realms/<realm-name>/scim/v2/Users
/realms/<realm-name>/scim/v2/Groups
권한 모델은 새로 만들지 않고 Admin REST API와 같은 realm-management 롤을 그대로 씁니다. 사용자 쓰기는 manage-users, 읽기는 view-users, 검색은 query-users/query-groups — 이미 Admin API용 서비스 계정이 있다면 추가 설정 없이 SCIM도 됩니다. 호출은 confidential 클라이언트만 허용되고, public 클라이언트는 거부됩니다.
설계에서 눈에 띄는 부분은 관리자 리소스 보호입니다. SCIM 클라이언트는 보통 광범위한 관리 권한으로 돌기 때문에, 침해당한 프로비저닝 클라이언트가 관리자 계정을 지우거나 관리자 그룹에 사용자를 밀어 넣는 시나리오를 문서가 명시적으로 막습니다 — 관리 롤을 가진 사용자·그룹은 SCIM으로 조회하면 최소 표현(id, schemas, userName 정도)만 나오고, 쓰기는 403으로 거부됩니다. 관리자 계정은 Admin 콘솔과 Admin REST API로만 만질 수 있습니다.
정직하게 한계를 적으면 — 지금 들어온 것은 Keycloak이 SCIM 서버가 되는 방향 하나입니다. HR 시스템이나 아이덴티티 거버넌스 플랫폼이 Keycloak에 사용자를 넣고 빼는 인바운드 프로비저닝은 이걸로 됩니다. 반대로 Keycloak이 SCIM 클라이언트가 되어 외부 SCIM 제공자에서 사용자를 연합해 오는 것은 별도 이슈로 아직 열려 있고, 문서도 외부 SCIM 서비스 제공자로부터의 사용자 연합과 푸시 기반 실시간 이벤트를 향후 릴리스 계획으로만 적어 둡니다. Keycloak에서 다운스트림 앱으로 밀어 주는 아웃바운드 프로비저닝도 이번 범위에 없습니다 — 그건 여전히 확장의 영역입니다. 그리고 프리뷰는 프리뷰입니다. 지원 대상이 아니며, 최종 형태가 바뀔 수 있습니다.
멀티클러스터 v2 — 외부 Infinispan 없이 (프리뷰)
지금까지 Keycloak의 멀티 사이트 HA(v1)는 사이트 간 세션 복제를 위해 외부 Infinispan(Data Grid) 클러스터를 따로 배포·운영해야 했고, 자동 페일오버를 위한 벤더 특화 fencing 인프라까지 요구했습니다. Keycloak HA 클러스터링 가이드에서 다뤘던 그 구조입니다. 운영해 본 사람은 알겠지만, 인증 서버의 HA를 위해 캐시 클러스터라는 또 하나의 분산 시스템을 돌보는 비용이 만만치 않습니다.
26.7의 멀티클러스터 v2는 그 외부 의존성을 통째로 걷어냅니다. 아키텍처는 이렇게 바뀝니다.
- Keycloak 인스턴스들이 내장 Infinispan 캐시로 클러스터 간 직접 연결됩니다.
- 동기 복제되는 데이터베이스가 단일 진실 공급원이 됩니다. 기능 플래그 이름이
stateless인 이유가 이것입니다 —Profile.java의 정의 그대로, 인증 세션·액션 토큰·로그인 실패 데이터를 DB에 저장해서 여러 클러스터가 DB만으로 연결되게 합니다. - 사이트 간 캐시 무효화는 DB 기반 outbox 패턴으로 처리됩니다.
- 로드 밸런서가 외부 fencing 없이 사이트 다운을 감지합니다.
여기까지만 들으면 지리적 DR까지 되는 것처럼 들리는데, 공식 가이드가 못을 박아 둔 제약을 그대로 옮기면 이렇습니다.
- 단일 리전 또는 그에 준하는 저지연 환경 전용입니다. 동기 복제되는 고가용 데이터베이스가 필수이고, 클러스터에서 DB까지의 읽기/쓰기/커밋 지연은 5ms 미만 권장, 10ms 미만 필수입니다. 대륙 간 액티브-액티브 DR을 기대하면 안 됩니다.
- 팀이 정기 테스트하는 구성(벤더 자체 측정)은 같은 AWS 리전 안의 단일 AZ OpenShift(ROSA HCP) 클러스터 두 개 + 가용 영역 간 동기 복제 리더를 둔 Aurora PostgreSQL 17.5 + AWS Global Accelerator이고, 테스트 부하는 사용자 100만 명에 초당 300 요청입니다. 이 범위를 넘는 규모는 직접 검증하라고 명시합니다.
- 장애 시나리오에 따라 수 분의 다운타임이 있을 수 있고, DB 벤더에 따라 수동 개입이 필요할 수 있습니다. 노드 장애 감지는 기본값 기준 1분 이내입니다.
운영 관점에서 하나 더 — Profile.java에서 이 기능은 FeatureUpdatePolicy.SHUTDOWN으로 선언돼 있습니다. 플래그를 켜거나 끌 때 롤링이 안 되고 클러스터 전체 셧다운이 필요하다는 뜻입니다. 이미 돌고 있는 프로덕션에 무중단으로 끼워 넣는 종류의 기능이 아닙니다.
요약하면 v2는 "외부 Infinispan 운영을 없앤 리전 내 다중 클러스터 가용성"이지, "멀리 떨어진 두 데이터센터"가 아닙니다. 대신 얻는 것은 분명합니다 — 관리할 분산 시스템이 하나 줄고, Kubernetes나 AWS 같은 특정 환경 요구도 사라집니다. 부하가 테스트 범위 안이고 DB를 동기 복제로 운영할 수 있는 조직이라면, v1의 운영 복잡도와 맞바꿀 가치가 있는 트레이드입니다.
여담 하나. 태그 시점의 릴리스 노트 원문은 이 기능을 하이라이트에서는 프리뷰로, 본문 제목에서는 experimental로 적는 불일치가 있었고(main 브랜치에서 프리뷰로 정리됐습니다), 코드의 Profile.java는 처음부터 PREVIEW였습니다. 릴리스 노트와 코드가 갈릴 때는 코드가 맞습니다.
Organizations — 멀티테넌시 위임이 현실적으로
멀티테넌트 SaaS SSO 아키텍처에서 다룬 것처럼, Keycloak의 Organizations는 realm 하나 안에서 여러 테넌트(조직)를 관리하는 기능입니다. 그런데 지금까지 조직을 관리하려면 manage-realm이라는 고권한 롤이 필요했습니다 — 테넌트 관리자에게 realm 전체 관리 권한을 주는 셈이라, 위임이라고 부르기 민망한 구조였습니다.
26.7이 이걸 손봤습니다.
- 전용 realm 관리 롤 세 개가 생겼습니다:
manage-organizations(조직 전체 읽기·쓰기),view-organizations(읽기 전용),query-organizations(목록·검색만). 기존query-users/query-clients패턴과 같은 결입니다.manage-realm은 하위 호환을 위해 여전히 조직 관리 권한을 함축합니다. - 조직이 Fine-Grained Admin Permissions의 1급 리소스 타입이 됐습니다. 특정 조직 하나만 관리할 수 있는 위임 관리자를 만들 수 있고, FGAP가 켜져 있으면 조직 멤버 조회도 사용자 수준 권한을 존중해서 볼 수 있는 멤버만 반환합니다.
- 조직 그룹에 realm/client 롤을 매핑할 수 있게 됐습니다. 조직 그룹에 롤을 한 번 달면 멤버 전원의
realm_access/resource_access클레임에 자동 반영되고, Organization Group Membership 프로토콜 매퍼의 옵션을 켜면 organization 클레임 안에 조직별로 정리해 넣을 수도 있습니다. 수백 명 규모 테넌트에서 멤버마다 롤을 다는 대신 그룹 단위로 관리하라는 이야기입니다.
브레이킹도 하나 딸려 왔습니다. 조직 멤버 목록 API가 이제 기본으로 brief 표현을 반환합니다. 전체 사용자 표현이 필요하면 쿼리 파라미터를 명시해야 합니다.
GET /admin/realms/{realm}/organizations/{id}/members?briefRepresentation=false
조직 초대 목록의 email/firstName/lastName 필터도 부분 일치에서 대소문자 무시 정확 일치로 바뀌었습니다 — 부분 일치가 필요하면 search 파라미터를 쓰라고 안내합니다. 이 API들에 의존하는 자동화가 있다면 응답과 필터 동작이 달라졌는지 먼저 확인하십시오.
업그레이드에서 밟기 쉬운 것들
이번 업그레이드 가이드에서 운영자가 실제로 밟을 만한 것들을 골랐습니다. 전체 목록은 업그레이드 가이드 원문을 보십시오.
PostgreSQL 비동기 커밋이 기본으로 켜집니다. persisted user sessions, client sessions, login failures, events처럼 휘발성 테이블만 갱신하는 트랜잭션은 이제 PostgreSQL의 async commit으로 처리됩니다(로그아웃은 여전히 동기 커밋 강제). 성능을 위한 선택인데, 의미를 정확히 알아야 합니다 — PostgreSQL 문서 기준으로 비동기 커밋은 WAL이 디스크에 플러시되기 전에 커밋 성공을 돌려주며, 서버가 크래시하면 그 사이 커밋은 유실됩니다. 유실 창은 최대 wal_writer_delay(기본 200ms)의 3배입니다. 데이터가 깨지는 게 아니라 마지막 1초 미만의 세션·이벤트 쓰기가 사라지는 것이고, 사용자 입장에서는 재로그인으로 끝납니다. 다만 events 테이블이 포함된다는 점은 짚을 만합니다 — 크래시 직전의 로그인 이벤트가 감사 로그에서 빠질 수 있다는 뜻이라, 감사 요건이 엄격한 환경이라면 --spi-connections-jpa--quarkus--async-commit=false로 옵트아웃할지 판단이 필요합니다.
X.509 클라이언트 인증에 CA Subject DN 옵션이 생겼고, 사실상 필수가 됩니다. mTLS로 클라이언트를 인증하는 경우, 이제 관리 콘솔에서 신뢰 앵커 CA의 subject DN을 지정하는 옵션이 강제됩니다. 기존 설정은 당장은 동작하지만, 다음 메이저부터 서버 측 검증이 들어가 이 옵션 없는 생성·수정·임포트가 거부됩니다. 정확한 DN 대신 정규식으로 인증서를 매칭하던 옵션도 함께 폐기 예고됐습니다. TLS 종료 프록시 뒤에서 헤더로 인증서를 넘기는 구성이라면 truststore가 클라이언트 인증서 체인을 검증할 수 있게 맞춰져 있는지도 다시 확인해야 합니다.
셀프 등록 흐름이 바뀝니다. realm에서 셀프 등록과 Verify Email을 함께 켠 경우, 등록 폼에서 비밀번호 필드가 기본으로 사라집니다. 사용자는 프로필만 등록하고, 이메일을 검증한 뒤에 비밀번호(또는 OTP, 패스키)를 설정합니다. 검증 안 된 이메일로 크리덴셜부터 만드는 순서를 뒤집은 것인데, 등록 UX와 문서·스크린샷이 통째로 달라지는 변경입니다. 예전 동작으로 되돌리는 스위치가 있지만 deprecated로 표시돼 있습니다.
나머지는 압축해서 나열합니다.
- 셧다운 타임아웃이 1초에서 10초로 늘었고, 분산 캐시 리밸런스 완료를 기다린 뒤 내려갑니다. 오케스트레이터의 종료 유예(terminationGracePeriodSeconds 등)와 맞춰 두십시오.
shutdown-timeout옵션으로 조정 가능합니다. - 새로 생성되는 클라이언트 시크릿이 항상 86자입니다(HS512 엔트로피 확보 목적). 기존 시크릿은 그대로지만, 시크릿을 저장하는 쪽에 최대 길이 제약이 있다면 늘려야 합니다.
- 세션 쿠키 해시가 SHA-256에서 SHA-384로, 신규 aes-generated 키 기본 크기가 128비트에서 256비트로 올라갔습니다(둘 다 CNSA 2.0 정렬 목적, 기존 세션·기존 realm은 영향 없음).
- 26.5.4에서 도입 즉시 deprecated였던
view-system관리 롤이 보안상 이유로 제거됐습니다. 서버 전체 정보 조회는 이제 master realm의manage-realm보유자로 제한됩니다. - FreeMarker가 2.3.32 기본값으로 올라갔습니다. 레거시 지시자나
?api같은 내부 접근에 기대던 커스텀 로그인 테마는 업그레이드 후 반드시 테스트하십시오. 로그인 테마의 버튼 배치도 바뀌었습니다. - DPoP가 implicit/hybrid 플로우에서 거부됩니다. 프런트 채널로 액세스 토큰이 나가는 플로우에서는 sender-constrained 모델이 성립하지 않는다는 이유로, 해당 조합은 이제 에러입니다.
- Admin REST API에서 ID로 사용자를 조회할 때 서비스 계정이 더는 포함되지 않고, Identity Provider의 alias는 생성 후 변경 불가가 됐습니다.
- Authorization Services의 리소스 URI 템플릿 검증이 엄격해졌습니다. 경로 중간 와일드카드처럼 원래 동작하지 않던 패턴이 이제 생성·수정 시 거부되므로, 업그레이드 전에 리소스들의 uris 필드를 점검하라고 가이드가 사전 점검 쿼리까지 제공합니다.
폐기 레이더 — 지금 끄거나 갈아탈 것
- Identity Brokering API V1이 deprecated 됐습니다. 대체인 V2는 사용자에게 broker 롤을 다는 대신 클라이언트 단위 인가(외부 토큰 조회 허용 스위치 + IdP 허용 목록)로 바뀌고, confidential 클라이언트만 허용하며, POST + 표준 JSON 응답을 씁니다. V2는 이번 릴리스에서 지원되지만 기본 비활성이고, V1은 아직 기본 활성입니다 — 미래 릴리스에서 V1이 제거되고 V2가 기본이 될 예정이니, 외부 IdP 토큰을 꺼내 쓰는 애플리케이션이 있다면 지금부터 V2로 옮기는 게 맞습니다.
- Twitter Identity Broker가 제거 예고됐습니다. 레거시 OAuth 1.0a 엔드포인트에 의존하기 때문입니다. X의 OAuth 2.0 엔드포인트에 generic OAuth v2 IdP를 설정하는 것으로 갈아타고, 안 쓴다면
--features-disabled=twitter-broker로 꺼 둘 수 있습니다. - OIDC 클라이언트의 Bearer-only 스위치가 deprecated 됐습니다. 콘솔에서는 이미 사라졌고 REST로만 설정 가능했는데, 그마저 막힐 예정입니다. 그랜트 없는 OIDC 클라이언트로 같은 목적을 달성할 수 있습니다.
- WebAuthn 정책의 Require Discoverable Credential 옵션이 deprecated 됐습니다. 새 Discoverable Credential 옵션은 WebAuthn 명세의 residentKey 값(required/preferred/discouraged)을 그대로 지원합니다 — Yes/No 강제로는 표현할 수 없던 preferred가 iCloud Keychain, Google Password Manager, 1Password 같은 패스키 제공자와의 호환성에 중요합니다. 패스키 생태계가 지금 어디까지 왔는지는 패스키 크리덴셜 익스체인지 정리에서 다뤘습니다.
- SHA-1이 Keycloak 27에서 전면 제거됩니다. NIST의 SHA-1 은퇴 계획(2030년 완전 퇴역)을 근거로, 업그레이드 가이드는 Keycloak 안에서 SHA-1을 이미 은퇴한 것으로 간주하고 SHA-2/SHA-3 계열로 지금 옮기라고 적시합니다. SAML 서명 알고리즘이나 오래된 연동에서 SHA-1을 쓰고 있다면 27이 나오기 전에 정리해야 합니다.
그 밖의 표준 실험들 — 한 단락씩만
이번 릴리스에는 experimental 딱지를 단 표준 구현이 유난히 많습니다. 전부 기본 비활성이고, experimental은 프리뷰보다도 앞 단계라는 점을 전제로 훑습니다.
- Shared Signals Framework 송신자(
ssf): 로그아웃·크리덴셜 변경·계정 비활성화 같은 보안 이벤트를 서명된 SET(RFC 8417)으로 다운스트림에 거의 실시간 푸시합니다. CAEP 1.0과 RISC 1.0 프로파일, push(RFC 8935)/poll(RFC 8936) 전달을 지원하고, durable outbox로 재시작에도 이벤트를 잃지 않게 설계됐습니다. 토큰 리프레시 때까지 세션 무효화를 모르는 고전적 공백을 겨냥한 기능입니다. - AuthZEN Evaluation API(
authzen): OpenID AuthZEN 1.0의 PDP 역할을 구현했습니다. subject/resource/action을 보내면 기존 Authorization Services 정책으로 permit/deny를 돌려줍니다. 단건·배치 평가 모두 지원합니다. - Identity Assertion JWT Grant(
identity-assertion-jwt): 조직 간 인증 서버를 넘나들 때 재인증 없이 토큰을 받는 ID-JAG 드래프트의 부분 구현입니다. 현재는 수신 측 역할만 구현돼 있어 전체 플로우는 아직 안 됩니다. - 토큰 교환 위임(
token-exchange-delegation): 게이트웨이가 다운스트림에서 사용자를 대신해 행동하는 위임 시나리오용으로, delegation 파라미터화 스코프가 사용자 동의를 요구하고 리프레시마다 재평가됩니다. 토큰 교환의 배경은 RFC 8693 토큰 교환과 위임을 참고하십시오. - Admin API v2(
client-admin-api:v2): 엄격한 검증과 정확한 OpenAPI 명세를 갖춘 새 관리 API의 첫 리소스로 클라이언트 관리가 들어왔습니다. Operator가 이를 써서 KeycloakOIDCClient/KeycloakSAMLClient 커스텀 리소스로 클라이언트를 선언적으로 관리합니다. 기존 Admin REST API의 느슨한 검증과 부정확한 스펙이라는 오랜 불만에 대한 답이 시작된 셈입니다.
프리뷰에서 정식 지원으로 승격된 것은 SAML 클라이언트의 step-up 인증 하나입니다. OIDC에만 있던 인증 컨텍스트 요구가 SAML SP에도 열렸습니다.
그래서 언제 올리고, 무엇을 켜나
정리하면 이렇게 판단하겠습니다.
- 업그레이드 자체는 마이너 릴리스이고 위 목록이 전부 관리 가능한 수준이니 미룰 이유가 없습니다. 다만 올리기 전에 X.509 CA Subject DN 추가, 클라이언트 시크릿 길이 제약, 커스텀 테마 테스트, async commit 옵트아웃 여부, 셀프 등록 흐름 변화 네다섯 가지는 체크리스트로 도십시오.
- SCIM 프리뷰는 스테이징에서 켜 볼 가치가 충분합니다. 특히 Admin REST API로 프로비저닝 스크립트를 짜서 쓰던 조직이라면, 표준 프로토콜 + 기존 권한 모델 + 관리자 보호까지 갖춘 이 방향이 장기적으로 옳습니다. 다만 프로덕션 의존은 preview가 supported로 승격된 뒤가 맞고, Keycloak이 클라이언트가 되는 방향(외부 SCIM 연합, 다운스트림 푸시)은 아직 없다는 걸 전제로 설계하십시오.
- 멀티클러스터 v2는 지금 v1(외부 Infinispan) 운영에 지쳐 있고, 단일 리전 + 동기 복제 DB 조건을 맞출 수 있는 조직에게 실질적 단순화입니다. 반대로 지리적 DR이 요구사항이라면 이 기능은 답이 아닙니다 — 10ms 미만 DB 지연 요구가 그 선을 긋습니다. 켜고 끌 때 전체 셧다운이 필요하다는 점까지 계획에 넣으십시오.
- 조직 관리 롤 세 개는 프리뷰가 아니라 이번 릴리스의 조용한 실속입니다. 테넌트 관리자에게
manage-realm을 주고 있었다면 지금 바로 회수하고manage-organizations이하로 좁히는 것이 이번 업그레이드에서 얻을 수 있는 가장 확실한 보안 개선입니다.
마치며
Keycloak 26.7은 헤드라인(SCIM, 멀티클러스터 v2)만 보면 프리뷰 잔치지만, 그 아래에 깔린 방향은 일관됩니다 — 서드파티 확장과 외부 인프라가 메워 온 공백을 코어 표준 구현으로 흡수하고(SCIM, SSF, AuthZEN), 고권한 롤을 쪼개고(조직 관리 롤, view-system 제거), 오래된 느슨함을 조입니다(X.509 CA DN, URI 템플릿 검증, SHA-1 퇴역 예고). 자가 호스팅 IdP를 운영하는 입장에서는 반가운 방향이고, 그 대가는 업그레이드 가이드가 길어지는 것뿐입니다. 릴리스 노트만 읽고 넘어가지 말고, 업그레이드 가이드를 체크리스트 삼아 한 번 도는 것을 권합니다.
참고 자료
- Keycloak 26.7.0 릴리스 발표
- Keycloak 26.7.0 GitHub 릴리스 (2026-07-09)
- 릴리스 노트 원문 adoc (26.7.0 태그)
- 업그레이드 가이드 원문 adoc (26.7.0 태그)
- 관리 가이드 — Managing users and groups through SCIM
- Multi-cluster deployments (v2) 가이드
- 기능 플래그 정의 — Profile.java (26.7.0 태그)
- SCIM 지원 요청 이슈 #13484 (2022-08, open)
- 외부 SCIM 제공자 연합 이슈 #43531 (open)
- PostgreSQL — Asynchronous Commit
- NIST Retires SHA-1 Cryptographic Algorithm
Keycloak 26.7 — SCIM Promoted to Preview, Multi-Cluster v2 Without External Infinispan, and What to Watch in the Upgrade
- Introduction — One Minor Every Quarter, and This Time It's 26.7
- The SCIM API — a Four-Year-Old Issue Reaches Core (Preview)
- Multi-Cluster v2 — No More External Infinispan (Preview)
- Organizations — Multi-Tenancy Delegation Gets Practical
- What's Easy to Trip Over in the Upgrade
- Deprecation Radar — What to Turn Off or Migrate Off of Now
- Other Standards Experiments — One Paragraph Each
- So, When Do You Upgrade, and What Do You Turn On
- Closing
- References
Introduction — One Minor Every Quarter, and This Time It's 26.7
Keycloak has been shipping minors roughly every three months lately. By GitHub release dates, 26.5.0 landed on January 6, 2026, 26.6.0 on April 8, and 26.7.0 on July 9. Most minors are worth a quick skim of the release notes and nothing more, but this one has more for an operator to snag on — two long-awaited features (SCIM, multi-cluster without an external cache) landed in preview, and the breaking/notable list in the upgrade guide is unusually long.
This post is an operations-focused read built by cross-checking the official release notes against the repository's original adoc files (release notes, upgrade guide), plus Profile.java, which is where feature flags are actually defined. If Keycloak 26's architecture itself is new to you, read the Keycloak 26 architecture deep dive first.
The SCIM API — a Four-Year-Old Issue Reaches Core (Preview)
SCIM (System for Cross-domain Identity Management) is a protocol for reading and writing identity resources like users and groups across systems through a standard REST API (schema in RFC 7643, protocol in RFC 7644). It's taken for granted in commercial IdPs like Okta or Entra ID, but Keycloak core has never had it. The SCIM support request opened in August 2022 has racked up 300 reactions and is still open; in the meantime the gap has been filled by third-party extensions like scim-for-keycloak.
That gap has now started to close in core. Tracing the timeline through the code tells the story: the scim-api feature flag was quietly added to Profile.java as experimental in 26.6.0 (the 26.6.0 release notes don't mention it at all), and it was promoted to preview in 26.7.0. It's off by default, so you need --features=scim-api to turn it on, and even after that it has to be toggled per realm in the realm settings.
Per the SCIM chapter of the admin guide, the scope of the implementation is:
- Full create/read/update/PATCH/delete for users and groups, plus group membership management
- The complete SCIM filter syntax and pagination
- Custom schema extension via the Enterprise User extension (RFC 7643 §4.3) and User Profile attribute mapping
- A schema discovery endpoint
Endpoints are exposed per realm.
/realms/<realm-name>/scim/v2/ServiceProviderConfig
/realms/<realm-name>/scim/v2/ResourceTypes
/realms/<realm-name>/scim/v2/Schemas
/realms/<realm-name>/scim/v2/Users
/realms/<realm-name>/scim/v2/Groups
No new authorization model was built for this — it reuses the same realm-management roles as the Admin REST API. Writing users needs manage-users, reading needs view-users, and searching needs query-users/query-groups — if you already have a service account for the Admin API, SCIM works with no extra setup. Only confidential clients are allowed to call it; public clients are rejected.
One design choice worth noting is the protection of admin resources. SCIM clients typically run with broad management privileges, so the docs explicitly guard against a compromised provisioning client deleting admin accounts or pushing users into admin groups — SCIM lookups of users or groups that carry management roles return only a minimal representation (roughly id, schemas, userName), and writes to them are rejected with a 403. Admin accounts can still only be touched through the Admin console and the Admin REST API.
To be honest about the limits: what landed is only the direction where Keycloak becomes the SCIM server. That covers inbound provisioning — an HR system or identity governance platform pushing users into and out of Keycloak. Going the other way, Keycloak acting as a SCIM client to federate users in from an external SCIM provider is still tracked in a separate, still-open issue, and the docs only list federation from an external SCIM service provider and push-based real-time events as future-release plans. Outbound provisioning — Keycloak pushing changes to downstream apps — is also out of scope here; that remains extension territory. And preview is preview: it's unsupported, and the final shape can still change.
Multi-Cluster v2 — No More External Infinispan (Preview)
Until now, Keycloak's multi-site HA (v1) required standing up and operating a separate external Infinispan (Data Grid) cluster for cross-site session replication, on top of vendor-specific fencing infrastructure for automatic failover — the setup covered in the Keycloak HA clustering guide. If you've operated it, you know the cost of babysitting a second distributed system — the cache cluster — just to keep an auth server highly available isn't small.
26.7's multi-cluster v2 strips out that external dependency entirely. The architecture changes like this:
- Keycloak instances connect directly across clusters using an embedded Infinispan cache.
- A synchronously replicated database becomes the single source of truth. This is why the feature flag is named
stateless— per its definition inProfile.java, authentication sessions, action tokens, and login-failure data are stored in the DB so that multiple clusters can be tied together through the database alone. - Cross-site cache invalidation is handled with a DB-based outbox pattern.
- The load balancer detects site outages without external fencing.
That description alone might sound like it covers geographic DR too, but the official guide pins down the constraints, and carrying them over verbatim:
- It's built only for a single region, or an environment with equivalently low latency. A synchronously replicated, highly available database is mandatory, and the read/write/commit latency from the cluster to the DB should be under 5ms and must be under 10ms. Don't expect cross-continent active-active DR.
- The configuration the team regularly tests (vendor-measured) is two single-AZ OpenShift (ROSA HCP) clusters in the same AWS region, plus Aurora PostgreSQL 17.5 with a cross-AZ synchronous replication leader, plus AWS Global Accelerator, tested at a load of 1 million users and 300 requests per second. Anything beyond that scale is explicitly left for you to validate yourself.
- Depending on the failure scenario, downtime of several minutes is possible, and manual intervention may be needed depending on the DB vendor. Node-failure detection is under a minute by default.
One more thing from an operations angle — in Profile.java this feature is declared with FeatureUpdatePolicy.SHUTDOWN. That means toggling the flag on or off can't be rolled out gradually; it requires a full cluster shutdown. This isn't the kind of feature you slot into an already-running production system without downtime.
To sum up, v2 is "region-local multi-cluster availability with the external Infinispan operations removed," not "two data centers far apart." What you get in exchange is clear, though — one fewer distributed system to manage, and no more requirement to be locked into a specific environment like Kubernetes or AWS. If your load fits inside the tested envelope and your organization can run the DB with synchronous replication, it's a trade worth making against v1's operational complexity.
A side note: at tag time, the original release notes had an inconsistency — labeling this feature preview in the highlights but experimental in the body heading (it's been cleaned up to preview on the main branch), while Profile.java in code had it as PREVIEW from the start. When the release notes and the code disagree, trust the code.
Organizations — Multi-Tenancy Delegation Gets Practical
As covered in designing SSO for multi-tenant SaaS, Keycloak's Organizations feature manages multiple tenants (organizations) within a single realm. Until now, though, managing an organization required the high-privilege manage-realm role — effectively handing a tenant admin full realm management rights, which made "delegation" a bit of a stretch.
26.7 fixes that.
- Three dedicated realm management roles were added:
manage-organizations(full read/write on organizations),view-organizations(read-only), andquery-organizations(list/search only) — the same pattern as the existingquery-users/query-clientsroles.manage-realmstill implies organization management for backward compatibility. - Organizations are now a first-class resource type under Fine-Grained Admin Permissions. You can create a delegated admin scoped to a single organization, and when FGAP is enabled, organization member lookups also honor user-level permissions and only return members the caller is allowed to see.
- Realm/client roles can now be mapped onto organization groups. Attaching a role to an organization group once propagates it into every member's
realm_access/resource_accessclaims automatically, and enabling the relevant option on the Organization Group Membership protocol mapper lets you nest that into the organization claim per organization. In short: manage roles at the group level instead of attaching them per member for tenants with hundreds of people.
There's a breaking change bundled in too. The organization member list API now returns the brief representation by default. If you need the full user representation, you have to request it explicitly with a query parameter.
GET /admin/realms/{realm}/organizations/{id}/members?briefRepresentation=false
The email/firstName/lastName filters on the organization invitation list also changed from partial match to case-insensitive exact match — use the search parameter if you need partial matching. If you have automation depending on these APIs, check first whether the response shape and filter behavior changed under you.
What's Easy to Trip Over in the Upgrade
Here's what I picked out of this release's upgrade guide as things an operator is actually likely to hit. See the full upgrade guide for the complete list.
PostgreSQL asynchronous commit is now on by default. Transactions that only touch volatile tables — persisted user sessions, client sessions, login failures, events — are now handled with PostgreSQL's async commit (logout still forces synchronous commit). It's a performance-motivated change, but you need to understand exactly what it means: per the PostgreSQL docs, asynchronous commit returns success before the WAL is flushed to disk, and if the server crashes, commits in that window are lost. The loss window is at most three times wal_writer_delay (200ms by default). Nothing gets corrupted — what disappears is at most the last well-under-a-second of session/event writes, and from the user's perspective it just means logging back in. Worth calling out, though, is that the events table is included — that means a login event right before a crash could be missing from the audit log, so if you're in an environment with strict audit requirements, decide whether to opt out with --spi-connections-jpa--quarkus--async-commit=false.
X.509 client authentication gets a CA Subject DN option, and it's effectively mandatory now. If you're authenticating clients with mTLS, the admin console now enforces specifying the subject DN of the trust-anchor CA. Existing configurations keep working for now, but starting with the next major, server-side validation kicks in and creates/updates/imports without this option will be rejected. The option that let you match certificates by regex instead of an exact DN is also deprecated alongside this. If you're passing certificates through headers behind a TLS-terminating proxy, double-check that the truststore is set up to validate the client certificate chain.
The self-registration flow changes. If a realm has self-registration and Verify Email enabled together, the password field is now gone from the registration form by default. Users register with just a profile, and after their email is verified, they set a password (or OTP, or passkey). This flips the old order of creating credentials before the email is even verified — it's a change that touches the registration UX and every bit of documentation and screenshots along with it. There's a switch to restore the old behavior, but it's marked deprecated.
The rest, compressed into a list:
- The shutdown timeout went from 1 second to 10 seconds, and shutdown now waits for the distributed cache rebalance to finish before going down. Align this with your orchestrator's termination grace period (e.g.
terminationGracePeriodSeconds). Adjustable via theshutdown-timeoutoption. - Newly generated client secrets are now always 86 characters (to guarantee enough entropy for HS512). Existing secrets are untouched, but if wherever you store secrets has a max-length constraint, you'll need to raise it.
- The session cookie hash moved from SHA-256 to SHA-384, and the default size for newly generated aes-generated keys went from 128 bits to 256 bits (both for CNSA 2.0 alignment; existing sessions and existing realms are unaffected).
- The
view-systemadmin role, which was deprecated the moment it was introduced in 26.5.4, has been removed for security reasons. Server-wide info lookups are now restricted to holders ofmanage-realmin the master realm. - FreeMarker's default moved to 2.3.32. Custom login themes that lean on legacy directives or internal access like
?apimust be tested after upgrading. Button placement in the login theme has also changed. - DPoP is now rejected in implicit/hybrid flows. Because the sender-constrained model doesn't hold up in flows where the access token goes out over the front channel, that combination is now an error.
- The Admin REST API no longer includes service accounts when looking up a user by ID, and an Identity Provider's alias can no longer be changed once created.
- Authorization Services' resource URI template validation got stricter. Patterns that never actually worked to begin with, like a wildcard in the middle of a path, are now rejected at create/update time, so the guide even ships a pre-check query for auditing your resources'
urisfields before you upgrade.
Deprecation Radar — What to Turn Off or Migrate Off of Now
- Identity Brokering API V1 is deprecated. Its replacement, V2, switches from attaching a broker role to a user to per-client authorization (a switch that allows fetching external tokens, plus an IdP allow-list), only allows confidential clients, and uses POST with standard JSON responses. V2 is supported in this release but disabled by default, and V1 is still enabled by default — a future release will remove V1 and make V2 the default, so if you have applications pulling external IdP tokens, now's the time to start moving to V2.
- The Twitter Identity Broker is slated for removal, because it depends on the legacy OAuth 1.0a endpoints. Migrate by configuring a generic OAuth v2 IdP against X's OAuth 2.0 endpoints, and if you don't use it, you can disable it now with
--features-disabled=twitter-broker. - The Bearer-only switch on OIDC clients is deprecated. It's already gone from the console and only configurable via REST, and even that path is slated to be closed off. You can achieve the same goal with a grantless OIDC client.
- The Require Discoverable Credential option in the WebAuthn policy is deprecated. The new Discoverable Credential option directly supports the WebAuthn spec's residentKey values (required/preferred/discouraged) — the
preferredvalue, which a forced yes/no couldn't express, matters for compatibility with passkey providers like iCloud Keychain, Google Password Manager, and 1Password. Where the passkey ecosystem stands right now is covered in the rundown on passkey credential exchange. - SHA-1 will be fully removed in Keycloak 27. Citing NIST's SHA-1 retirement plan (full retirement by 2030), the upgrade guide treats SHA-1 as already retired within Keycloak and directs you to move to SHA-2/SHA-3 now. If you're still using SHA-1 for a SAML signing algorithm or in an older integration, clean it up before 27 ships.
Other Standards Experiments — One Paragraph Each
This release has an unusually large number of experimental-tagged standards implementations. All are off by default, and keep in mind experimental is a stage earlier than preview as you skim these.
- Shared Signals Framework sender (
ssf): pushes security events — logout, credential changes, account disablement — to downstream consumers in near real time as signed SETs (RFC 8417). It supports the CAEP 1.0 and RISC 1.0 profiles, both push (RFC 8935) and poll (RFC 8936) delivery, and is designed with a durable outbox so no events are lost across restarts. It targets the classic gap where a session doesn't get invalidated until the next token refresh. - AuthZEN Evaluation API (
authzen): implements the PDP role from OpenID AuthZEN 1.0. Send it a subject/resource/action and it returns permit/deny using your existing Authorization Services policies. Both single and batch evaluation are supported. - Identity Assertion JWT Grant (
identity-assertion-jwt): a partial implementation of the ID-JAG draft, which lets you obtain a token without re-authenticating when crossing auth servers between organizations. Only the receiving side is implemented right now, so the full flow doesn't work yet. - Token exchange delegation (
token-exchange-delegation): for delegation scenarios where a gateway acts on a user's behalf downstream — delegation-parameterized scopes require user consent and are re-evaluated on every refresh. For background on token exchange, see RFC 8693 token exchange and delegation. - Admin API v2 (
client-admin-api:v2): client management is the first resource in a new admin API built with strict validation and an accurate OpenAPI spec. The Operator uses it to declaratively manage clients via the KeycloakOIDCClient/KeycloakSAMLClient custom resources. It's the start of an answer to the long-standing complaint about the existing Admin REST API's loose validation and inaccurate spec.
The one thing promoted from preview to fully supported is step-up authentication for SAML clients — the authentication-context requirement that used to be OIDC-only is now open to SAML SPs as well.
So, When Do You Upgrade, and What Do You Turn On
Here's how I'd call it.
- The upgrade itself is a minor release, and everything on the list above is manageable, so there's no reason to hold off. Before you go, though, put five or so things on a checklist: adding the X.509 CA Subject DN, the client secret length constraint, testing custom themes, deciding whether to opt out of async commit, and the self-registration flow change.
- The SCIM preview is worth turning on in staging. If your organization has been writing provisioning scripts against the Admin REST API, this direction — standard protocol, the existing permission model, plus admin protection — is the right long-term call. Production dependency should wait until preview is promoted to supported, though, and design around the fact that Keycloak acting as the client (external SCIM federation, downstream push) doesn't exist yet.
- Multi-cluster v2 is a real simplification if you're tired of running v1 (external Infinispan) and your organization can meet the single-region-plus-synchronously-replicated-DB bar. If geographic DR is a requirement, on the other hand, this feature isn't the answer — the sub-10ms DB latency requirement draws that line clearly. Factor the full-shutdown requirement for toggling it on and off into your planning too.
- The three organization management roles aren't preview — they're the quiet, solid win of this release. If you've been handing tenant admins
manage-realm, clawing that back right now and scoping them down tomanage-organizationsor narrower is the single most concrete security improvement available in this upgrade.
Closing
Looking only at the headline items (SCIM, multi-cluster v2), Keycloak 26.7 reads like a preview showcase, but the direction underneath is consistent — it absorbs gaps that third-party extensions and external infrastructure used to fill into core standard implementations (SCIM, SSF, AuthZEN), splits apart high-privilege roles (the organization management roles, removing view-system), and tightens up old looseness (X.509 CA DN, URI template validation, the SHA-1 retirement notice). For anyone self-hosting an IdP, it's a welcome direction, and the only price is a longer upgrade guide. Don't just skim the release notes — walking through the upgrade guide as a checklist once is worth the time.
References
- Keycloak 26.7.0 release announcement
- Keycloak 26.7.0 GitHub release (2026-07-09)
- Original release notes adoc (26.7.0 tag)
- Original upgrade guide adoc (26.7.0 tag)
- Admin guide — Managing users and groups through SCIM
- Multi-cluster deployments (v2) guide
- Feature flag definitions — Profile.java (26.7.0 tag)
- SCIM support request issue #13484 (2022-08, open)
- External SCIM provider federation issue #43531 (open)
- PostgreSQL — Asynchronous Commit
- NIST Retires SHA-1 Cryptographic Algorithm