diff --git a/spring-security-modules/spring-security-oidc/pom.xml b/spring-security-modules/spring-security-oidc/pom.xml
index 2a413b1d27..70031b7396 100644
--- a/spring-security-modules/spring-security-oidc/pom.xml
+++ b/spring-security-modules/spring-security-oidc/pom.xml
@@ -24,6 +24,10 @@
org.springframework.boot
spring-boot-starter-oauth2-client
+
+ org.springframework.boot
+ spring-boot-starter-oauth2-resource-server
+
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/SpringOidcJwtAuthoritiesApplication.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/SpringOidcJwtAuthoritiesApplication.java
new file mode 100644
index 0000000000..4fa58f3578
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/SpringOidcJwtAuthoritiesApplication.java
@@ -0,0 +1,23 @@
+/**
+ *
+ */
+package com.baeldung.openid.oidc.jwtauthorities;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+
+import com.baeldung.openid.oidc.discovery.SpringOidcDiscoveryApplication;
+import com.baeldung.openid.oidc.utils.YamlLoaderInitializer;
+
+@SpringBootApplication
+public class SpringOidcJwtAuthoritiesApplication {
+
+ public static void main(String[] args) {
+ SpringApplication application = new SpringApplication(SpringOidcJwtAuthoritiesApplication.class);
+ ApplicationContextInitializer yamlInitializer = new YamlLoaderInitializer("jwtauthorities-application.yml");
+ application.addInitializers(yamlInitializer);
+ application.run(args);
+ }
+}
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/AccountToken.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/AccountToken.java
new file mode 100644
index 0000000000..a48a0889aa
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/AccountToken.java
@@ -0,0 +1,23 @@
+package com.baeldung.openid.oidc.jwtauthorities.config;
+
+import java.util.Collection;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+
+import com.baeldung.openid.oidc.jwtauthorities.domain.Account;
+
+public class AccountToken extends JwtAuthenticationToken {
+ private static final long serialVersionUID = 1L;
+ private final Account account;
+
+ public AccountToken(Jwt jwt, Collection extends GrantedAuthority> authorities, String name, Account account) {
+ super(jwt, authorities, name);
+ this.account = account;
+ }
+
+ public Account getAccount() {
+ return account;
+ }
+}
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/CustomJwtAuthenticationConverter.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/CustomJwtAuthenticationConverter.java
new file mode 100644
index 0000000000..57b9809bc6
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/CustomJwtAuthenticationConverter.java
@@ -0,0 +1,36 @@
+package com.baeldung.openid.oidc.jwtauthorities.config;
+
+import java.util.Collection;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.security.oauth2.jwt.JwtClaimNames;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+
+import com.baeldung.openid.oidc.jwtauthorities.domain.Account;
+import com.baeldung.openid.oidc.jwtauthorities.service.AccountService;
+
+public class CustomJwtAuthenticationConverter implements Converter {
+
+ private final Converter> jwtGrantedAuthoritiesConverter;
+ private final String principalClaimName;
+ private AccountService accountService;
+
+ public CustomJwtAuthenticationConverter(AccountService accountService, Converter> jwtGrantedAuthoritiesConverter, String principalClaimName) {
+ this.accountService = accountService;
+ this.jwtGrantedAuthoritiesConverter = jwtGrantedAuthoritiesConverter;
+ this.principalClaimName = principalClaimName != null ? principalClaimName : JwtClaimNames.SUB;
+ }
+
+ @Override
+ public AbstractAuthenticationToken convert(Jwt source) {
+
+ Collection authorities = jwtGrantedAuthoritiesConverter.convert(source);
+ String principalClaimValue = source.getClaimAsString(this.principalClaimName);
+ Account acc = accountService.findAccountByPrincipal(principalClaimValue);
+ return new AccountToken(source, authorities, principalClaimValue, acc);
+ }
+
+}
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/JwtMappingProperties.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/JwtMappingProperties.java
new file mode 100644
index 0000000000..71a7004300
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/JwtMappingProperties.java
@@ -0,0 +1,49 @@
+package com.baeldung.openid.oidc.jwtauthorities.config;
+
+import java.util.Map;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties(prefix = "baeldung.jwt.mapping")
+public class JwtMappingProperties {
+
+ private String authoritiesPrefix;
+ private String authoritiesClaimName;
+ private String principalClaimName;
+ private Map scopes;
+
+ public String getAuthoritiesClaimName() {
+ return authoritiesClaimName;
+ }
+
+ public void setAuthoritiesClaimName(String authoritiesClaimName) {
+ this.authoritiesClaimName = authoritiesClaimName;
+ }
+
+ public String getAuthoritiesPrefix() {
+ return authoritiesPrefix;
+ }
+
+ public void setAuthoritiesPrefix(String authoritiesPrefix) {
+ this.authoritiesPrefix = authoritiesPrefix;
+ }
+
+
+ public String getPrincipalClaimName() {
+ return principalClaimName;
+ }
+
+ public void setPrincipalClaimName(String principalClaimName) {
+ this.principalClaimName = principalClaimName;
+ }
+
+ public Map getScopes() {
+ return scopes;
+ }
+
+ public void setScopes(Map scopes) {
+ this.scopes = scopes;
+ }
+
+
+}
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/MappingJwtGrantedAuthoritiesConverter.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/MappingJwtGrantedAuthoritiesConverter.java
new file mode 100644
index 0000000000..0b47082294
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/MappingJwtGrantedAuthoritiesConverter.java
@@ -0,0 +1,84 @@
+package com.baeldung.openid.oidc.jwtauthorities.config;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
+
+public class MappingJwtGrantedAuthoritiesConverter implements Converter> {
+
+ private static final Collection WELL_KNOWN_AUTHORITIES_CLAIM_NAMES = Arrays.asList("scope", "scp");
+
+ private final Map scopes;
+ private String authoritiesClaimName = null;
+ private String authorityPrefix = "SCOPE_";
+
+ MappingJwtGrantedAuthoritiesConverter(Map scopes) {
+ this.scopes = scopes == null ? Collections.emptyMap(): scopes;
+ }
+
+ public void setAuthoritiesClaimName(String authoritiesClaimName) {
+ this.authoritiesClaimName = authoritiesClaimName;
+ }
+
+ public void setAuthorityPrefix(String authorityPrefix) {
+ this.authorityPrefix = authorityPrefix;
+ }
+
+ @Override
+ public Collection convert(Jwt jwt) {
+
+ Collection tokenScopes = parseScopesClaim(jwt);
+ if ( tokenScopes.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ return tokenScopes.stream()
+ .map(s -> scopes.getOrDefault(s, s))
+ .map(s -> this.authorityPrefix + s)
+ .map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toCollection(HashSet::new));
+ }
+
+ protected Collection parseScopesClaim(Jwt jwt) {
+
+ String scopeClaim;
+
+ if ( this.authoritiesClaimName == null ) {
+ scopeClaim = WELL_KNOWN_AUTHORITIES_CLAIM_NAMES.stream()
+ .filter( claim -> jwt.hasClaim(claim))
+ .findFirst()
+ .orElse(null);
+
+ if ( scopeClaim == null ) {
+ return Collections.emptyList();
+ }
+ }
+ else {
+ scopeClaim = this.authoritiesClaimName;
+ }
+
+ Object v = jwt.getClaim(scopeClaim);
+ if ( v == null ) {
+ return Collections.emptyList();
+ }
+
+ if ( v instanceof String) {
+ return Arrays.asList(v.toString().split(" "));
+ }
+ else if ( v instanceof Collection ) {
+ return ((Collection>)v).stream()
+ .map( s -> s.toString())
+ .collect(Collectors.toCollection(HashSet::new));
+ }
+ return Collections.emptyList();
+ }
+}
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/SecurityConfig.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/SecurityConfig.java
new file mode 100644
index 0000000000..7495831b54
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/config/SecurityConfig.java
@@ -0,0 +1,75 @@
+package com.baeldung.openid.oidc.jwtauthorities.config;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
+import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.util.StringUtils;
+
+import com.baeldung.openid.oidc.jwtauthorities.service.AccountService;
+
+@Configuration
+@EnableConfigurationProperties(JwtMappingProperties.class)
+@EnableMethodSecurity
+public class SecurityConfig {
+
+ private final JwtMappingProperties mappingProps;
+ private final AccountService accountService;
+
+ public SecurityConfig(JwtMappingProperties mappingProps, AccountService accountService) {
+ this.mappingProps = mappingProps;
+ this.accountService = accountService;
+ }
+
+ @Bean
+ public String jwtGrantedAuthoritiesPrefix() {
+ return mappingProps.getAuthoritiesPrefix();
+ }
+
+ @Bean
+ public Converter> jwtGrantedAuthoritiesConverter() {
+ MappingJwtGrantedAuthoritiesConverter converter = new MappingJwtGrantedAuthoritiesConverter(mappingProps.getScopes());
+
+ if (StringUtils.hasText(mappingProps.getAuthoritiesPrefix())) {
+ converter.setAuthorityPrefix(mappingProps.getAuthoritiesPrefix()
+ .trim());
+ }
+
+ if (StringUtils.hasText(mappingProps.getAuthoritiesClaimName())) {
+ converter.setAuthoritiesClaimName(mappingProps.getAuthoritiesClaimName());
+ }
+ return converter;
+ }
+
+ @Bean
+ public Converter customJwtAuthenticationConverter(AccountService accountService) {
+ return new CustomJwtAuthenticationConverter(
+ accountService,
+ jwtGrantedAuthoritiesConverter(),
+ mappingProps.getPrincipalClaimName());
+ }
+
+ @Bean
+ SecurityFilterChain customJwtSecurityChain(HttpSecurity http) throws Exception {
+ // @formatter:off
+ return http.oauth2ResourceServer(oauth2 -> {
+ oauth2.jwt()
+ .jwtAuthenticationConverter(customJwtAuthenticationConverter(accountService));
+ })
+ .build();
+ // @formatter:on
+ }
+
+}
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/domain/Account.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/domain/Account.java
new file mode 100644
index 0000000000..f0227c8628
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/domain/Account.java
@@ -0,0 +1,26 @@
+package com.baeldung.openid.oidc.jwtauthorities.domain;
+
+public class Account {
+
+ private final Long id;
+ private final String branch;
+ private final String accountNumber;
+
+ public Account(Long id, String branch, String accountNumber) {
+ this.id = id;
+ this.branch = branch;
+ this.accountNumber = accountNumber;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getBranch() {
+ return branch;
+ }
+
+ public String getAccountNumber() {
+ return accountNumber;
+ }
+}
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/service/AccountService.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/service/AccountService.java
new file mode 100644
index 0000000000..e10a26209c
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/service/AccountService.java
@@ -0,0 +1,14 @@
+package com.baeldung.openid.oidc.jwtauthorities.service;
+
+import org.springframework.stereotype.Service;
+
+import com.baeldung.openid.oidc.jwtauthorities.domain.Account;
+
+@Service
+public class AccountService {
+
+ public Account findAccountByPrincipal(String principal) {
+ // NOTE: real-world code would typically perform some sort of DB lookup
+ return new Account(1l, "0001", "101888444-0");
+ }
+}
diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/web/controllers/UserRestController.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/web/controllers/UserRestController.java
new file mode 100644
index 0000000000..a3b4d1d5cd
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/jwtauthorities/web/controllers/UserRestController.java
@@ -0,0 +1,49 @@
+package com.baeldung.openid.oidc.jwtauthorities.web.controllers;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.openid.oidc.jwtauthorities.config.AccountToken;
+import com.baeldung.openid.oidc.jwtauthorities.domain.Account;
+
+@RestController
+@RequestMapping("/user")
+public class UserRestController {
+
+ @GetMapping("/authorities")
+ @PreAuthorize("hasAuthority(@jwtGrantedAuthoritiesPrefix + 'profile.read')")
+ public Map getPrincipalInfo( JwtAuthenticationToken principal) {
+
+ Collection authorities = principal.getAuthorities()
+ .stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.toList());
+
+ Map info = new HashMap<>();
+ info.put("name", principal.getName());
+ info.put("authorities", authorities);
+ info.put("tokenAttributes", principal.getTokenAttributes());
+
+ if ( principal instanceof AccountToken ) {
+ info.put( "account", ((AccountToken)principal).getAccount());
+ }
+
+ return info;
+ }
+
+ @GetMapping("/account/{accountNumber}")
+ @PreAuthorize("authentication.account.accountNumber == #accountNumber")
+ public Account getAccountById(@PathVariable("accountNumber") String accountNumber, AccountToken authentication) {
+ return authentication.getAccount();
+ }
+}
diff --git a/spring-security-modules/spring-security-oidc/src/main/resources/application.yml b/spring-security-modules/spring-security-oidc/src/main/resources/application.yml
index f303fcecd1..bb23047dfe 100644
--- a/spring-security-modules/spring-security-oidc/src/main/resources/application.yml
+++ b/spring-security-modules/spring-security-oidc/src/main/resources/application.yml
@@ -4,4 +4,3 @@ server:
logging:
level:
org.springframework.web.client.RestTemplate: DEBUG
-
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-oidc/src/main/resources/jwtauthorities-application.yml b/spring-security-modules/spring-security-oidc/src/main/resources/jwtauthorities-application.yml
new file mode 100644
index 0000000000..384b406465
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/main/resources/jwtauthorities-application.yml
@@ -0,0 +1,15 @@
+spring:
+ security:
+ oauth2:
+ resourceserver:
+ jwt:
+# issuer-uri: https://sts.windows.net/2e9fde3a-38ec-44f9-8bcd-c184dc1e8033/
+ issuer-uri: http://localhost:8083/auth/realms/baeldung
+baeldung:
+ jwt:
+ mapping:
+ authorities-prefix: "MY_SCOPE_"
+ principal-claim-name: preferred_username
+ scopes:
+ profile: profile.read
+ "profile_read": profile.read
diff --git a/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/jwtauthorities/config/CustomJwtAuthenticationConverterUnitTest.java b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/jwtauthorities/config/CustomJwtAuthenticationConverterUnitTest.java
new file mode 100644
index 0000000000..09f1efa228
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/jwtauthorities/config/CustomJwtAuthenticationConverterUnitTest.java
@@ -0,0 +1,59 @@
+package com.baeldung.openid.oidc.jwtauthorities.config;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.security.oauth2.jwt.Jwt;
+
+import com.baeldung.openid.oidc.jwtauthorities.service.AccountService;
+
+class CustomJwtAuthenticationConverterUnitTest {
+
+ @Test
+ void testGivenCustomJwtAuthenticationConverter_whenConvert_thenReturnAccountToken() {
+
+ AccountService accountService = new AccountService();
+ MappingJwtGrantedAuthoritiesConverter authoritiesConverter = new MappingJwtGrantedAuthoritiesConverter(new HashMap<>());
+
+ CustomJwtAuthenticationConverter converter = new CustomJwtAuthenticationConverter(
+ accountService, authoritiesConverter, null);
+
+ Jwt jwt = Jwt.withTokenValue("NOTUSED")
+ .header("typ", "JWT")
+ .subject("user")
+ .claim("scp", "openid email profile")
+ .build();
+
+ Object auth = converter.convert(jwt);
+ assertTrue(auth instanceof AccountToken, "Authentication must be instance of AccountToken");
+ AccountToken token = AccountToken.class.cast(auth);
+
+ assertEquals("user", token.getName());
+ }
+
+ @Test
+ void testGivenCustomPrincipalClaimName_whenConvert_thenReturnAccountToken() {
+
+ AccountService accountService = new AccountService();
+ MappingJwtGrantedAuthoritiesConverter authoritiesConverter = new MappingJwtGrantedAuthoritiesConverter(new HashMap<>());
+
+ CustomJwtAuthenticationConverter converter = new CustomJwtAuthenticationConverter(
+ accountService, authoritiesConverter, "preferred_username");
+
+ Jwt jwt = Jwt.withTokenValue("NOTUSED")
+ .header("typ", "JWT")
+ .claim("preferred_username", "user")
+ .claim("scp", "openid email profile")
+ .build();
+
+ Object auth = converter.convert(jwt);
+ assertTrue(auth instanceof AccountToken, "Authentication must be instance of AccountToken");
+ AccountToken token = AccountToken.class.cast(auth);
+
+ assertEquals("user", token.getName());
+ }
+
+}
diff --git a/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/jwtauthorities/config/MappingJwtGrantedAuthoritiesConverterUnitTest.java b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/jwtauthorities/config/MappingJwtGrantedAuthoritiesConverterUnitTest.java
new file mode 100644
index 0000000000..90b943ce53
--- /dev/null
+++ b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/jwtauthorities/config/MappingJwtGrantedAuthoritiesConverterUnitTest.java
@@ -0,0 +1,91 @@
+package com.baeldung.openid.oidc.jwtauthorities.config;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
+
+class MappingJwtGrantedAuthoritiesConverterUnitTest {
+
+ @Test
+ void testGivenConverterWithScopeMap_whenConvert_thenResultHasMappedAuthorities() {
+ Jwt jwt = Jwt.withTokenValue("NOTUSED")
+ .header("typ", "JWT")
+ .subject("user")
+ .claim("scp", "openid email profile")
+ .build();
+
+ Map scopeMap = new HashMap<>();
+ scopeMap.put("profile", "profile.read");
+ MappingJwtGrantedAuthoritiesConverter converter = new MappingJwtGrantedAuthoritiesConverter(scopeMap);
+ Collection result = converter.convert(jwt);
+
+ assertTrue("Result must contain the authoriry 'SCOPE_profile.read'",
+ result.contains(new SimpleGrantedAuthority("SCOPE_profile.read")));
+ }
+
+ @Test
+ void testGivenConverterWithCustomScopeClaim_whenConvert_thenResultHasAuthorities() {
+ Jwt jwt = Jwt.withTokenValue("NOTUSED")
+ .header("typ", "JWT")
+ .subject("user")
+ .claim("myscope_claim", "openid email profile")
+ .build();
+
+ Map scopeMap = new HashMap<>();
+ MappingJwtGrantedAuthoritiesConverter converter = new MappingJwtGrantedAuthoritiesConverter(scopeMap);
+ converter.setAuthoritiesClaimName("myscope_claim");
+ Collection result = converter.convert(jwt);
+
+ assertTrue("Result must contain the authoriry 'SCOPE_profile'",
+ result.contains(new SimpleGrantedAuthority("SCOPE_profile")));
+ }
+
+ @Test
+ void testGivenTokenWithNonMappedScope_whenConvert_thenResultHasOriginalScope() {
+ Jwt jwt = Jwt.withTokenValue("NOTUSED")
+ .header("typ", "JWT")
+ .subject("user")
+ .claim("scp", "openid email profile custom")
+ .build();
+
+ Map scopeMap = new HashMap<>();
+ scopeMap.put("profile", "profile.read");
+ MappingJwtGrantedAuthoritiesConverter converter = new MappingJwtGrantedAuthoritiesConverter(scopeMap);
+ Collection result = converter.convert(jwt);
+
+ assertTrue("Result must contain the authority SCOPE_custom",
+ result.contains(new SimpleGrantedAuthority("SCOPE_custom")));
+ }
+
+
+ @Test
+ void testGivenConverterWithCustomPrefix_whenConvert_thenAllAuthoritiesMustHaveTheCustomPrefix() {
+ Jwt jwt = Jwt.withTokenValue("NOTUSED")
+ .header("typ", "JWT")
+ .subject("user")
+ .claim("scp", "openid email profile custom")
+ .build();
+
+ Map scopeMap = new HashMap<>();
+ scopeMap.put("profile", "profile.read");
+ MappingJwtGrantedAuthoritiesConverter converter = new MappingJwtGrantedAuthoritiesConverter(scopeMap);
+ converter.setAuthorityPrefix("MY_SCOPE");
+ Collection result = converter.convert(jwt);
+
+ long count = result.stream()
+ .map(GrantedAuthority::getAuthority)
+ .filter(s -> !s.startsWith("MY_SCOPE"))
+ .count();
+
+ assertTrue("All authorities names must start with custom prefix", count == 0 );
+ }
+
+}