diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverter.java index ab020a3fc89..5fcab4f46e7 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,10 +45,14 @@ public final class JwtGrantedAuthoritiesConverter implements Converter WELL_KNOWN_AUTHORITIES_CLAIM_NAMES = Arrays.asList("scope", "scp"); private String authorityPrefix = DEFAULT_AUTHORITY_PREFIX; + private String authoritiesSplitRegex = DEFAULT_AUTHORITIES_SPLIT_REGEX; + private String authoritiesClaimName; /** @@ -77,6 +81,18 @@ public void setAuthorityPrefix(String authorityPrefix) { this.authorityPrefix = authorityPrefix; } + /** + * Sets the regex to use for splitting the value of the authorities claim into + * {@link GrantedAuthority authorities}. Defaults to + * {@link JwtGrantedAuthoritiesConverter#DEFAULT_AUTHORITIES_SPLIT_REGEX}. + * @param authoritiesSplitRegex The regex used to split the authorities + * @since 6.1 + */ + public void setAuthoritiesSplitRegex(String authoritiesSplitRegex) { + Assert.notNull(authoritiesSplitRegex, "authoritiesSplitRegex cannot be null"); + this.authoritiesSplitRegex = authoritiesSplitRegex; + } + /** * Sets the name of token claim to use for mapping {@link GrantedAuthority * authorities} by this converter. Defaults to @@ -113,7 +129,7 @@ private Collection getAuthorities(Jwt jwt) { Object authorities = jwt.getClaim(claimName); if (authorities instanceof String) { if (StringUtils.hasText((String) authorities)) { - return Arrays.asList(((String) authorities).split(" ")); + return Arrays.asList(((String) authorities).split(this.authoritiesSplitRegex)); } return Collections.emptyList(); } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java index ff3cc30b8a7..d3ba0c2b507 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -256,4 +256,18 @@ public void convertWhenTokenHasNoCustomClaimNameThenCustomClaimNameAttributeIsTr assertThat(authorities).isEmpty(); } + @Test + public void convertWithCustomAuthoritiesSplitRegexWhenTokenHasScopeAttributeThenTranslatedToAuthorities() { + // @formatter:off + Jwt jwt = TestJwts.jwt() + .claim("scope", "message:read,message:write") + .build(); + // @formatter:on + JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); + jwtGrantedAuthoritiesConverter.setAuthoritiesSplitRegex(","); + Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), + new SimpleGrantedAuthority("SCOPE_message:write")); + } + }