Merge pull request #51619 from yyuneu

Closes gh-51619

* gh-51619:
  Honor authorities-claim-delimiter when set on its own
This commit is contained in:
Andy Wilkinson
2026-09-08 16:43:39 +01:00
5 changed files with 26 additions and 2 deletions
@@ -265,6 +265,11 @@ class ReactiveOAuth2ResourceServerJwtConfiguration {
}
@ConditionalOnProperty("spring.security.oauth2.resourceserver.jwt.authorities-claim-delimiter")
static class OnAuthoritiesClaimDelimiter {
}
}
}
@@ -257,6 +257,11 @@ class OAuth2ResourceServerJwtConfiguration {
}
@ConditionalOnProperty("spring.security.oauth2.resourceserver.jwt.authorities-claim-delimiter")
static class OnAuthoritiesClaimDelimiter {
}
}
}
@@ -53,7 +53,7 @@ public final class JwtConverterCustomizationsArgumentsProvider implements Argume
String principalClaimProperty = "spring.security.oauth2.resourceserver.jwt.principal-claim-name="
+ customPrincipalClaim;
String[] customPrefixProps = { jwkSetUriProperty, authorityPrefixProperty };
String[] customDelimiterProps = { jwkSetUriProperty, authorityPrefixProperty, authoritiesDelimiterProperty };
String[] customDelimiterProps = { jwkSetUriProperty, authoritiesDelimiterProperty };
String[] customAuthoritiesClaimProps = { jwkSetUriProperty, authoritiesClaimProperty };
String[] customPrincipalClaimProps = { jwkSetUriProperty, principalClaimProperty };
String[] allJwtConverterProps = { jwkSetUriProperty, authorityPrefixProperty, authoritiesDelimiterProperty,
@@ -84,7 +84,7 @@ public final class JwtConverterCustomizationsArgumentsProvider implements Argume
Arguments.of(Named.named("Custom prefix for GrantedAuthority", customPrefixProps),
noAuthoritiesCustomizationsJwt, subjectValue, customPrefixAuthorities),
Arguments.of(Named.named("Custom delimiter for JWT scopes", customDelimiterProps),
customAuthoritiesDelimiterJwt, subjectValue, customPrefixAuthorities),
customAuthoritiesDelimiterJwt, subjectValue, defaultPrefixAuthorities),
Arguments.of(Named.named("Custom JWT authority claim name", customAuthoritiesClaimProps),
customAuthoritiesClaimJwt, subjectValue, defaultPrefixAuthorities),
Arguments.of(Named.named("Custom JWT principal claim name", customPrincipalClaimProps),
@@ -701,6 +701,13 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests {
.run((context) -> assertThat(context).hasSingleBean(ReactiveJwtAuthenticationConverter.class));
}
@Test
void shouldConfigureJwtConverterIfAuthoritiesClaimDelimiterIsSet() {
this.contextRunner
.withPropertyValues("spring.security.oauth2.resourceserver.jwt.authorities-claim-delimiter=dummy")
.run((context) -> assertThat(context).hasSingleBean(ReactiveJwtAuthenticationConverter.class));
}
@ParameterizedTest(name = "{0}")
@ArgumentsSource(JwtConverterCustomizationsArgumentsProvider.class)
void autoConfigurationShouldConfigureResourceServerWithJwtConverterCustomizations(String[] properties, Jwt jwt,
@@ -738,6 +738,13 @@ class OAuth2ResourceServerAutoConfigurationTests {
.run((context) -> assertThat(context).hasSingleBean(JwtAuthenticationConverter.class));
}
@Test
void shouldConfigureJwtConverterIfAuthoritiesClaimDelimiterIsSet() {
this.contextRunner
.withPropertyValues("spring.security.oauth2.resourceserver.jwt.authorities-claim-delimiter=dummy")
.run((context) -> assertThat(context).hasSingleBean(JwtAuthenticationConverter.class));
}
@Test
void jwtAuthenticationConverterByJwtConfigIsConditionalOnMissingBean() {
String propertiesPrincipalClaim = "principal_from_properties";