1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.bremersee.spring.boot.autoconfigure.security.authentication;
18
19 import static java.util.Objects.isNull;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.bremersee.spring.boot.autoconfigure.security.authentication.AuthenticationProperties.JwtConverterProperties;
24 import org.bremersee.spring.security.core.mapping.CaseTransformation;
25 import org.bremersee.spring.security.core.mapping.authority.NormalizedGrantedAuthoritiesMapper;
26 import org.bremersee.spring.security.core.mapping.group.GroupsMapper;
27 import org.bremersee.spring.security.core.mapping.group.NormalizedGroupsMapper;
28 import org.bremersee.spring.security.oauth2.server.resource.authentication.JsonPathJwtConverter;
29 import org.bremersee.spring.security.oauth2.server.resource.authentication.JsonPathJwtProperties;
30 import org.springframework.beans.factory.ObjectProvider;
31 import org.springframework.boot.autoconfigure.AutoConfiguration;
32 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
33 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
34 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
35 import org.springframework.boot.context.event.ApplicationReadyEvent;
36 import org.springframework.boot.context.properties.EnableConfigurationProperties;
37 import org.springframework.boot.security.autoconfigure.web.reactive.ReactiveWebSecurityAutoConfiguration;
38 import org.springframework.boot.security.autoconfigure.web.servlet.ServletWebSecurityAutoConfiguration;
39 import org.springframework.context.annotation.Bean;
40 import org.springframework.context.event.EventListener;
41 import org.springframework.core.convert.converter.Converter;
42 import org.springframework.security.authentication.AbstractAuthenticationToken;
43 import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
44 import org.springframework.security.oauth2.jwt.Jwt;
45 import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
46 import org.springframework.util.ClassUtils;
47
48
49
50
51
52
53 @ConditionalOnClass(name = {
54 "org.bremersee.spring.security.oauth2.server.resource.authentication.JsonPathJwtConverter",
55 "org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter",
56 "org.springframework.boot.security.autoconfigure.web.reactive.ReactiveWebSecurityAutoConfiguration",
57 "org.springframework.boot.security.autoconfigure.web.servlet.ServletWebSecurityAutoConfiguration"
58 })
59 @AutoConfiguration(
60 before = {
61 ServletWebSecurityAutoConfiguration.class,
62 ReactiveWebSecurityAutoConfiguration.class
63 })
64 @ConditionalOnProperty(
65 prefix = "spring.security.oauth2.resourceserver.jwt",
66 name = "jwk-set-uri")
67 @EnableConfigurationProperties(AuthenticationProperties.class)
68 public class JwtConverterAutoConfiguration {
69
70 private static final Log log = LogFactory.getLog(JwtConverterAutoConfiguration.class);
71
72 private final JwtConverterProperties properties;
73
74
75
76
77
78
79 public JwtConverterAutoConfiguration(AuthenticationProperties properties) {
80 this.properties = properties.getJwtConverter();
81 }
82
83
84
85
86 @EventListener(ApplicationReadyEvent.class)
87 public void init() {
88 log.info(String.format("""
89
90 *********************************************************************************
91 * %s
92 * properties = %s
93 *********************************************************************************""",
94 ClassUtils.getUserClass(getClass()).getSimpleName(),
95 properties));
96 }
97
98
99
100
101
102
103
104
105 @ConditionalOnMissingBean({JwtAuthenticationConverter.class})
106 @Bean
107 public Converter<Jwt, AbstractAuthenticationToken> jwtConverter(
108 ObjectProvider<GrantedAuthoritiesMapper> rolesMapperProvider,
109 ObjectProvider<GroupsMapper> groupsMapperProvider) {
110
111 log.info("Creating new jwt authentication converter.");
112
113 GrantedAuthoritiesMapper grantedAuthoritiesMapper = rolesMapperProvider
114 .getIfAvailable(() -> new NormalizedGrantedAuthoritiesMapper(
115 properties.getDefaultRoles(),
116 properties.toRoleMappings(),
117 properties.getRolePrefix(),
118 getCaseTransformation(properties.getRoleCaseTransformation()),
119 properties.toRoleStringReplacements()));
120
121 GroupsMapper groupsMapper = groupsMapperProvider
122 .getIfAvailable(() -> new NormalizedGroupsMapper(
123 properties.getDefaultGroups(),
124 properties.toGroupMappings(),
125 properties.getGroupPrefix(),
126 getCaseTransformation(properties.getGroupCaseTransformation()),
127 properties.toGroupStringReplacements()));
128
129 JsonPathJwtProperties jsonPathJwtProperties = JsonPathJwtProperties.builder()
130 .nameJsonPath(properties.getNameJsonPath())
131 .firstNameJsonPath(properties.getFirstNameJsonPath())
132 .lastNameJsonPath(properties.getLastNameJsonPath())
133 .emailJsonPath(properties.getEmailJsonPath())
134 .rolesJsonPath(properties.getRolesJsonPath())
135 .rolesValueList(properties.isRolesValueList())
136 .rolesValueSeparator(properties.getRolesValueSeparator())
137 .authoritiesMapper(grantedAuthoritiesMapper)
138 .groupsJsonPath(properties.getGroupsJsonPath())
139 .groupsValueList(properties.isGroupsValueList())
140 .groupsValueSeparator(properties.getGroupsValueSeparator())
141 .groupsMapper(groupsMapper)
142 .build();
143
144 return new JsonPathJwtConverter(jsonPathJwtProperties);
145 }
146
147 private CaseTransformation getCaseTransformation(
148 AuthenticationProperties.CaseTransformation source) {
149 return isNull(source) ? CaseTransformation.NONE : CaseTransformation.valueOf(source.name());
150 }
151 }