# Keycloak's nested roles, mapped with configuration only. # # `authorities-claim-expressions` is a Spring Boot 4 property. Each entry is a SpEL # expression evaluated against the claim map, so a nested claim needs no Java. # # NOTE THE QUOTES around 'reports-api'. Inside a SpEL indexer the contents are an # expression, not a literal key, so [resource_access][reports-api][roles] parses as # `reports` MINUS `api` and blows up with EL1008E. ExpressionJwtGrantedAuthoritiesConverter # catches ExpressionException, substitutes an empty authority list, and logs the reason at # TRACE only - so the failure surfaces as a 403 with nothing in the log to explain it. # See application-propsroles-broken.yaml for the other spelling, and docs/14. # # Two more consequences of taking this route: # * `authority-prefix` is ONE value applied to every expression. A mixed mapping - # SCOPE_ for scopes, ROLE_ for roles - cannot be expressed here. # * naming expressions REPLACES the default JwtGrantedAuthoritiesConverter, so the # SCOPE_* authorities it produced from the `scope` claim disappear unless you add # `[scope]` as an expression too - and then it gets the ROLE_ prefix as well. spring: security: oauth2: resourceserver: jwt: principal-claim-name: preferred_username authority-prefix: "ROLE_" authorities-claim-expressions: - "[realm_access][roles]" - "[resource_access]['reports-api'][roles]"