Migrate project to spring-boot-3

This commit is contained in:
Konstantinos Triantafyllou 2024-07-26 12:46:29 +03:00
parent e91a0e6af8
commit da0bced79a
12 changed files with 118 additions and 105 deletions

24
pom.xml
View File

@ -4,10 +4,10 @@
<parent> <parent>
<groupId>eu.dnetlib</groupId> <groupId>eu.dnetlib</groupId>
<artifactId>uoa-spring-boot-parent</artifactId> <artifactId>uoa-spring-boot-parent</artifactId>
<version>1.0.0</version> <version>2.0.1</version>
</parent> </parent>
<artifactId>uoa-authorization-library</artifactId> <artifactId>uoa-authorization-library</artifactId>
<version>2.1.5-SNAPSHOT</version> <version>3.0.0-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>uoa-authorization-library</name> <name>uoa-authorization-library</name>
<scm> <scm>
@ -28,27 +28,17 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId> <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency> </dependency>
<!-- Redis -->
<dependency> <dependency>
<groupId>org.springframework.session</groupId> <groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId> <artifactId>spring-session-data-redis</artifactId>
</dependency> </dependency>
<!-- Redis Client -->
<dependency> <dependency>
<groupId>biz.paluch.redis</groupId> <groupId>redis.clients</groupId>
<artifactId>lettuce</artifactId> <artifactId>jedis</artifactId>
<version>4.3.3.Final</version>
</dependency>
<dependency>
<groupId>org.mitre</groupId>
<artifactId>openid-connect-client</artifactId>
<version>1.3.0</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -1,22 +1,32 @@
package eu.dnetlib.uoaauthorizationlibrary.configuration; package eu.dnetlib.uoaauthorizationlibrary.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration @Configuration
@EnableConfigurationProperties({SecurityConfig.class, GlobalVars.class}) @EnableConfigurationProperties({SecurityConfig.class, GlobalVars.class})
@ComponentScan(basePackages = { "eu.dnetlib.uoaauthorizationlibrary" }) @ComponentScan(basePackages = { "eu.dnetlib.uoaauthorizationlibrary" })
public class AuthorizationConfiguration { public class AuthorizationConfiguration {
private final SecurityConfig securityConfig;
@Autowired
public AuthorizationConfiguration(SecurityConfig securityConfig) {
this.securityConfig = securityConfig;
}
@Bean @Bean
public WebMvcConfigurer corsConfigurer() { public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() { return new WebMvcConfigurer() {
@Override @Override
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") registry.addMapping("/**")
.allowedOriginPatterns("*" + securityConfig.getDomain())
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS") .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
.allowCredentials(true); .allowCredentials(true);
} }

View File

@ -15,7 +15,6 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
@RestController @RestController
@CrossOrigin(origins = "*")
@RequestMapping("/authorization-library") @RequestMapping("/authorization-library")
public class AuthorizationLibraryCheckDeployController { public class AuthorizationLibraryCheckDeployController {
private final Logger log = LogManager.getLogger(this.getClass()); private final Logger log = LogManager.getLogger(this.getClass());
@ -26,7 +25,7 @@ public class AuthorizationLibraryCheckDeployController {
@Autowired @Autowired
private GlobalVars globalVars; private GlobalVars globalVars;
@RequestMapping(value = {"", "/health_check"}, method = RequestMethod.GET) @RequestMapping(value = {"","/", "/health_check"}, method = RequestMethod.GET)
public String hello() { public String hello() {
log.debug("Hello from uoa-authorization-library!"); log.debug("Hello from uoa-authorization-library!");
return "Hello from uoa-authorization-library!"; return "Hello from uoa-authorization-library!";

View File

@ -6,7 +6,9 @@ import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.CookieSerializer; import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer; import org.springframework.session.web.http.DefaultCookieSerializer;
@ -15,26 +17,37 @@ import org.springframework.session.web.http.DefaultCookieSerializer;
@Configuration @Configuration
public class RedisConfig { public class RedisConfig {
private final SecurityConfig securityConfig; private final SecurityConfig properties;
private static final Logger logger = LogManager.getLogger(RedisConfig.class); private static final Logger logger = LogManager.getLogger(RedisConfig.class);
@Autowired @Autowired
public RedisConfig(SecurityConfig securityConfig) {this.securityConfig = securityConfig;} public RedisConfig(SecurityConfig properties) {
this.properties = properties;
}
@Bean @Bean
public LettuceConnectionFactory connectionFactory() { public JedisConnectionFactory connectionFactory() {
logger.info(String.format("Redis connection listens to %s:%s ", securityConfig.getRedis().getHost(), securityConfig.getRedis().getPort())); logger.info(String.format("Redis connection listens to %s:%s ", properties.getRedis().getHost(), properties.getRedis().getPort()));
LettuceConnectionFactory factory = new LettuceConnectionFactory(securityConfig.getRedis().getHost(), Integer.parseInt(securityConfig.getRedis().getPort())); RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(properties.getRedis().getHost(), Integer.parseInt(properties.getRedis().getPort()));
if (securityConfig.getRedis().getPassword() != null) factory.setPassword(securityConfig.getRedis().getPassword()); if (properties.getRedis().getPassword() != null)
return factory; configuration.setPassword(properties.getRedis().getPassword());
return new JedisConnectionFactory(configuration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory());
return template;
} }
@Bean @Bean
public CookieSerializer cookieSerializer() { public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer(); DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName(securityConfig.getSession()); serializer.setCookieName(properties.getSession());
serializer.setCookiePath("/"); serializer.setCookiePath("/");
serializer.setDomainName(securityConfig.getDomain()); serializer.setDomainName(properties.getDomain());
return serializer; return serializer;
} }
} }

View File

@ -1,20 +1,30 @@
package eu.dnetlib.uoaauthorizationlibrary.redis.security; package eu.dnetlib.uoaauthorizationlibrary.redis.security;
import eu.dnetlib.uoaauthorizationlibrary.security.EntryPoint; import eu.dnetlib.uoaauthorizationlibrary.security.EntryPoint;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@EnableWebSecurity @EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @EnableMethodSecurity(securedEnabled = true, proxyTargetClass = true)
@Configuration
public class WebSecurityConfig {
@Override @Bean
protected void configure(HttpSecurity http) throws Exception { public EntryPoint entryPoint() {
http.csrf().disable(); return new EntryPoint();
http.authorizeRequests().anyRequest().permitAll(); }
http.httpBasic().authenticationEntryPoint(new EntryPoint());
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable);
http.exceptionHandling(handler -> handler.authenticationEntryPoint(this.entryPoint()));
http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
} }
} }

View File

@ -1,13 +1,16 @@
package eu.dnetlib.uoaauthorizationlibrary.security; package eu.dnetlib.uoaauthorizationlibrary.security;
import org.mitre.openid.connect.model.OIDCAuthenticationToken; import eu.dnetlib.uoaauthorizationlibrary.stateless.utils.UserInfo;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component(value = "AuthorizationService") @Component(value = "AuthorizationService")
@ -85,7 +88,7 @@ public class AuthorizationService {
if(authentication instanceof OpenAIREAuthentication) { if(authentication instanceof OpenAIREAuthentication) {
return ((OpenAIREAuthentication) authentication).getUser().getSub(); return ((OpenAIREAuthentication) authentication).getUser().getSub();
} else { } else {
return ((OIDCAuthenticationToken) authentication).getUserInfo().getSub(); return Objects.requireNonNull(this.getOidcUser()).getSubject();
} }
} }
return null; return null;
@ -97,7 +100,17 @@ public class AuthorizationService {
if(authentication instanceof OpenAIREAuthentication) { if(authentication instanceof OpenAIREAuthentication) {
return ((OpenAIREAuthentication) authentication).getUser().getEmail(); return ((OpenAIREAuthentication) authentication).getUser().getEmail();
} else { } else {
return ((OIDCAuthenticationToken) authentication).getUserInfo().getEmail(); return Objects.requireNonNull(this.getOidcUser()).getEmail();
}
}
return null;
}
private DefaultOidcUser getOidcUser() {
Authentication authentication = getAuthentication();
if (authentication != null && authentication.isAuthenticated()) {
if (authentication instanceof OAuth2AuthenticationToken token) {
return (DefaultOidcUser) token.getPrincipal();
} }
} }
return null; return null;
@ -105,7 +118,7 @@ public class AuthorizationService {
private Authentication getAuthentication() { private Authentication getAuthentication() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication instanceof OpenAIREAuthentication || authentication instanceof OIDCAuthenticationToken) { if(authentication instanceof OpenAIREAuthentication || authentication instanceof OAuth2AuthenticationToken) {
return authentication; return authentication;
} else { } else {
return null; return null;

View File

@ -1,10 +1,9 @@
package eu.dnetlib.uoaauthorizationlibrary.security; package eu.dnetlib.uoaauthorizationlibrary.security;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
public class EntryPoint implements AuthenticationEntryPoint { public class EntryPoint implements AuthenticationEntryPoint {

View File

@ -1,12 +1,11 @@
package eu.dnetlib.uoaauthorizationlibrary.stateless.security; package eu.dnetlib.uoaauthorizationlibrary.stateless.security;
import eu.dnetlib.uoaauthorizationlibrary.security.OpenAIREAuthentication; import eu.dnetlib.uoaauthorizationlibrary.security.OpenAIREAuthentication;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
@Component @Component
@ -19,20 +18,15 @@ public class AuthorizationFilter implements Filter {
this.authorizationProvider = authorizationProvider; this.authorizationProvider = authorizationProvider;
} }
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override @Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
OpenAIREAuthentication auth = authorizationProvider.getAuthentication((HttpServletRequest) req); if (request instanceof HttpServletRequest req) {
if(auth.isAuthenticated()) { OpenAIREAuthentication auth = authorizationProvider.getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(auth); if (auth.isAuthenticated()) {
SecurityContextHolder.getContext().setAuthentication(auth);
}
} }
filterChain.doFilter(req, res); chain.doFilter(request, response);
}
@Override
public void destroy() {
} }
} }

View File

@ -1,26 +0,0 @@
package eu.dnetlib.uoaauthorizationlibrary.stateless.security;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class AuthorizationFilterConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final AuthorizationFilter filter;
@Override
public void init(HttpSecurity http) throws Exception {
http.csrf().disable();
}
public AuthorizationFilterConfigurer(AuthorizationFilter filter) {
this.filter = filter;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
}
}

View File

@ -3,11 +3,10 @@ package eu.dnetlib.uoaauthorizationlibrary.stateless.security;
import eu.dnetlib.uoaauthorizationlibrary.security.OpenAIREAuthentication; import eu.dnetlib.uoaauthorizationlibrary.security.OpenAIREAuthentication;
import eu.dnetlib.uoaauthorizationlibrary.stateless.utils.AuthorizationUtils; import eu.dnetlib.uoaauthorizationlibrary.stateless.utils.AuthorizationUtils;
import eu.dnetlib.uoaauthorizationlibrary.stateless.utils.UserInfo; import eu.dnetlib.uoaauthorizationlibrary.stateless.utils.UserInfo;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component @Component
public class AuthorizationProvider { public class AuthorizationProvider {

View File

@ -2,29 +2,42 @@ package eu.dnetlib.uoaauthorizationlibrary.stateless.security;
import eu.dnetlib.uoaauthorizationlibrary.security.EntryPoint; import eu.dnetlib.uoaauthorizationlibrary.security.EntryPoint;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@EnableWebSecurity @EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @EnableMethodSecurity(securedEnabled = true, proxyTargetClass = true)
@Configuration
public class WebSecurityConfig {
private final AuthorizationFilter filter; private final AuthorizationFilter filter;
@Autowired @Autowired
WebSecurityConfig(AuthorizationFilter filter) { public WebSecurityConfig(AuthorizationFilter filter) {
this.filter = filter; this.filter = filter;
} }
@Override
protected void configure(HttpSecurity http) throws Exception { @Bean
http.apply(new AuthorizationFilterConfigurer(filter)); public EntryPoint entryPoint() {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); return new EntryPoint();
http.authorizeRequests().anyRequest().permitAll(); }
http.httpBasic().authenticationEntryPoint(new EntryPoint());
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable);
http.addFilterBefore(filter, BasicAuthenticationFilter.class);
http.exceptionHandling(handler -> handler.authenticationEntryPoint(this.entryPoint()));
http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
return http.build();
} }
} }

View File

@ -1,6 +1,8 @@
package eu.dnetlib.uoaauthorizationlibrary.stateless.utils; package eu.dnetlib.uoaauthorizationlibrary.stateless.utils;
import eu.dnetlib.uoaauthorizationlibrary.configuration.SecurityConfig; import eu.dnetlib.uoaauthorizationlibrary.configuration.SecurityConfig;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -8,9 +10,6 @@ import org.springframework.http.*;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;