Compare commits
28 Commits
master
...
spring-boo
|
@ -54,9 +54,9 @@ atlassian-ide-plugin.xml
|
|||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
crashlytics.securityProperties
|
||||
crashlytics-build.securityProperties
|
||||
fabric.securityProperties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
|
109
README.md
109
README.md
|
@ -1,9 +1,9 @@
|
|||
# Authorization Library
|
||||
|
||||
Authorization library is a library that provides a Spring Security (4.x.x) process
|
||||
Authorization library is a library that provides a Spring Security (6.x.x) process
|
||||
in order to authorize the endpoints of a service base on OpenAIRE Authorities.
|
||||
It can be used with two different session strategies, a stateless and
|
||||
a Redis http session.
|
||||
a Redis http session. Also, it includes swagger configuration.
|
||||
|
||||
## Stateless
|
||||
|
||||
|
@ -19,15 +19,15 @@ user's session, but with a cost of an extra http request per request.
|
|||
<dependency>
|
||||
<groupId>eu.dnetlib</groupId>
|
||||
<artifactId>uoa-authorization-library</artifactId>
|
||||
<version>2.1.2</version>
|
||||
<version>3.0.4</version>
|
||||
</dependency>
|
||||
|
||||
#### Spring Application/Configuration
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.configuration.AuthorizationConfiguration;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.SecurityConfiguration;
|
||||
|
||||
@PropertySources({@PropertySource("classpath:authorization.properties")})
|
||||
@Import(AuthorizationConfiguration.class)
|
||||
@PropertySources({@PropertySource("classpath:authorization.securityProperties")})
|
||||
@Import(SecurityConfiguration.class)
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
|
@ -38,6 +38,7 @@ user's session, but with a cost of an extra http request per request.
|
|||
|
||||
authorization.security.userInfoUrl = http://<domain>/login-service/userInfo # Required, default ""
|
||||
authorization.security.session=<session-cookie-name> # Default openAIRESession
|
||||
authorization.security.domain=<domain-suffix> # e.g openaire.eu Default: di.uoa.gr
|
||||
|
||||
## Redis
|
||||
|
||||
|
@ -53,16 +54,16 @@ where session is stored.
|
|||
<dependency>
|
||||
<groupId>eu.dnetlib</groupId>
|
||||
<artifactId>uoa-authorization-library</artifactId>
|
||||
<version>2.1.2</version>
|
||||
<version>3.0.1</version>
|
||||
<classifier>redis</classifier>
|
||||
</dependency>
|
||||
|
||||
#### Spring Application/Configuration
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.configuration.AuthorizationConfiguration;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.SecurityConfiguration;
|
||||
|
||||
@PropertySources({@PropertySource("classpath:authorization.properties")})
|
||||
@Import(AuthorizationConfiguration.class)
|
||||
@PropertySources({@PropertySource("classpath:authorization.securityProperties")})
|
||||
@Import(SecurityConfiguration.class)
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
|
@ -71,12 +72,43 @@ where session is stored.
|
|||
|
||||
#### Configuration
|
||||
|
||||
authorization.secuirty.redis.host=<redis-ip> # Default localhost
|
||||
authorization.secuirty.redis.port=<redis-port> # Default 6379
|
||||
authorization.secuirty.redis.password=<redis-password> # Default ""
|
||||
authorization.security.domain=<domain-suffix> # e.g openaire.eu
|
||||
authorization.security.redis.host=<redis-ip> # Default localhost
|
||||
authorization.security.redis.port=<redis-port> # Default 6379
|
||||
authorization.security.redis.password=<redis-password> # Default ""
|
||||
authorization.security.domain=<domain-suffix> # e.g openaire.eu Default: di.uoa.gr
|
||||
authorization.security.session=<session-cookie-name> # Default openAIRESession
|
||||
|
||||
### Custom WebSecurity
|
||||
|
||||
In case you want to create a custom WebSecurity Configuration you have to:
|
||||
|
||||
1. **@Import(AuthorizationConfiguration.class)** instead of SecurityConfiguration.
|
||||
2. (Optional) On your WebSecurity Configuration inject WebSecurity component and use security method
|
||||
in order to pre-build HttpSecurity with the default security.
|
||||
|
||||
e.g
|
||||
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity(securedEnabled = true, proxyTargetClass = true)
|
||||
@Configuration
|
||||
public class WebSecurityConfig {
|
||||
|
||||
private final WebSecurity webSecurity;
|
||||
|
||||
@Autowired
|
||||
public WebSecurityConfig(WebSecurity webSecurity) {
|
||||
this.webSecurity = webSecurity;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http = webSecurity.security(http);
|
||||
// Custom Security Configuration
|
||||
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## Authorize Requests
|
||||
|
||||
|
@ -119,34 +151,31 @@ e.g
|
|||
@RequestMapping(value = "{type}/{id}", method = RequestMethod.GET)
|
||||
public Entity getEntity(@PathVariable("type") String type, @PathVariable("id") String id) {}
|
||||
|
||||
## Spring Security (5.x.x) - Spring boot (2.x.x)
|
||||
|
||||
Because of MitreID dependency, in order to use this library
|
||||
with redis HttpSession, service has to use spring security (4.x.x).
|
||||
The only way to use this library in a project with spring security 5.x.x
|
||||
is the Stateless strategy with the following modification in Application
|
||||
class:
|
||||
## Exception Handling
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.configuration.AuthorizationConfiguration;
|
||||
This library provides exception handling if an error is occurred.
|
||||
|
||||
@PropertySources({@PropertySource("classpath:authorization.properties")})
|
||||
@Import(AuthorizationConfiguration.class)
|
||||
public class Application {
|
||||
### Known Http Exceptions
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
- UnauthorizedException (401)
|
||||
- ForbiddenException (403)
|
||||
- NotFoundException (404)
|
||||
- ConflictException (409)
|
||||
- UnprocessableException (422)
|
||||
|
||||
@Bean
|
||||
public WebMvcConfigurer corsConfigurer() {
|
||||
return new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
|
||||
.allowedOriginPatterns("*")
|
||||
.allowCredentials(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Create your own Exception with HttpStatus by extending **HttpException** class.
|
||||
By default, any other RuntimeException produces Http Status 400 (BAD REQUEST).
|
||||
|
||||
## Swagger configuration
|
||||
|
||||
This library by default includes swagger configuration, which is accessible only by PORTAL ADMIN users.
|
||||
Optional set API info securityProperties in your project configuration file:
|
||||
|
||||
api.title = <Title>
|
||||
api.description = <Description>
|
||||
api.version = ${project.version}
|
||||
|
||||
### Disable UI and/or API-docs
|
||||
springdoc.swagger-ui.enabled=false
|
||||
springdoc.api-docs.enabled=false
|
||||
|
|
30
pom.xml
30
pom.xml
|
@ -4,10 +4,10 @@
|
|||
<parent>
|
||||
<groupId>eu.dnetlib</groupId>
|
||||
<artifactId>uoa-spring-boot-parent</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.0.3</version>
|
||||
</parent>
|
||||
<artifactId>uoa-authorization-library</artifactId>
|
||||
<version>2.1.5-SNAPSHOT</version>
|
||||
<version>3.0.5-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>uoa-authorization-library</name>
|
||||
<scm>
|
||||
|
@ -28,27 +28,23 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<artifactId>spring-boot-starter-oauth2-client</artifactId>
|
||||
</dependency>
|
||||
<!-- Redis -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-data-redis</artifactId>
|
||||
</dependency>
|
||||
<!-- Redis Client -->
|
||||
<dependency>
|
||||
<groupId>biz.paluch.redis</groupId>
|
||||
<artifactId>lettuce</artifactId>
|
||||
<version>4.3.3.Final</version>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
<!-- Swagger -->
|
||||
<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>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>${spring-doc-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
@ -65,7 +61,7 @@
|
|||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/eu/dnetlib/uoaauthorizationlibrary/redis/**</exclude>
|
||||
<exclude>**/eu/dnetlib/uoaauthorizationlibrary/authorization/redis/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
@ -78,7 +74,7 @@
|
|||
<configuration>
|
||||
<classifier>redis</classifier>
|
||||
<excludes>
|
||||
<exclude>**/eu/dnetlib/uoaauthorizationlibrary/stateless/**</exclude>
|
||||
<exclude>**/eu/dnetlib/uoaauthorizationlibrary/authorization/stateless/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.API;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.GlobalVars;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.SecurityProperties;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.CheckProperties;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({SecurityProperties.class, GlobalVars.class, API.class})
|
||||
@ComponentScan(basePackages = {"eu.dnetlib.uoaauthorizationlibrary.authorization"})
|
||||
public class AuthorizationConfiguration {
|
||||
|
||||
private final SecurityProperties properties;
|
||||
private final GlobalVars globalVars;
|
||||
private final CheckProperties checkProperties;
|
||||
|
||||
@Autowired
|
||||
public AuthorizationConfiguration(SecurityProperties properties, GlobalVars globalVars, CheckProperties checkProperties) {
|
||||
this.properties = properties;
|
||||
this.globalVars = globalVars;
|
||||
this.checkProperties = checkProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
RestTemplate restTemplate() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||
converter.setObjectMapper(new ObjectMapper());
|
||||
restTemplate.getMessageConverters().add(converter);
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void checkProperties() {
|
||||
if(properties.getDomain() == null || properties.getDomain().isEmpty()) {
|
||||
throw new RuntimeException("authorization.security.domain is missing!");
|
||||
} else if(properties.getSession() == null || properties.getSession().isEmpty()) {
|
||||
throw new RuntimeException("authorization.security.session is missing!");
|
||||
}
|
||||
this.checkProperties.checkProperties(properties);
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("authorization.security.domain", properties.getDomain());
|
||||
map.put("authorization.security.session", properties.getSession());
|
||||
this.checkProperties.getProperties(map, properties);
|
||||
if (GlobalVars.date != null) {
|
||||
map.put("Date of deploy", GlobalVars.date.toString());
|
||||
}
|
||||
if (globalVars.getBuildDate() != null) {
|
||||
map.put("Date of build", globalVars.getBuildDate());
|
||||
}
|
||||
if (globalVars.getVersion() != null) {
|
||||
map.put("Version", globalVars.getVersion());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
@Configuration
|
||||
@Import(AuthorizationConfiguration.class)
|
||||
@ComponentScan(basePackageClasses = {WebSecurityConfig.class})
|
||||
public class SecurityConfiguration { }
|
|
@ -0,0 +1,28 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.SecurityMode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity(securedEnabled = true, proxyTargetClass = true)
|
||||
@Configuration
|
||||
public class WebSecurityConfig {
|
||||
|
||||
private final SecurityMode securityMode;
|
||||
|
||||
@Autowired
|
||||
public WebSecurityConfig(SecurityMode securityMode) {
|
||||
this.securityMode = securityMode;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
return securityMode.security(http).build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.configuration;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("api")
|
||||
public class API {
|
||||
private String title;
|
||||
private String description;
|
||||
private String version;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.configuration;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.configuration;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.configuration;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.configuration;
|
||||
|
||||
public class Redis {
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.configuration;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.configuration;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("authorization.security")
|
||||
public class SecurityConfig {
|
||||
public class SecurityProperties {
|
||||
|
||||
private Redis redis = new Redis();
|
||||
private String userInfoUrl;
|
|
@ -0,0 +1,27 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.configuration;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class SwaggerConfig {
|
||||
|
||||
private final API api;
|
||||
|
||||
@Autowired
|
||||
public SwaggerConfig(API api) {
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
return new OpenAPI()
|
||||
.info(new Info()
|
||||
.title(api.getTitle())
|
||||
.version(api.getVersion())
|
||||
.description(api.getDescription()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.controllers;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.AuthorizationConfiguration;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/authorization-library")
|
||||
public class AuthorizationLibraryCheckDeployController {
|
||||
private final Logger log = LogManager.getLogger(this.getClass());
|
||||
|
||||
private final AuthorizationConfiguration configuration;
|
||||
|
||||
@Autowired
|
||||
public AuthorizationLibraryCheckDeployController(AuthorizationConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@RequestMapping(value = {"","/", "/health_check"}, method = RequestMethod.GET)
|
||||
public ResponseEntity<String> hello() {
|
||||
log.debug("Hello from uoa-authorization-library!");
|
||||
return ResponseEntity.ok("Hello from uoa-authorization-library!");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyAuthority(@AuthorizationService.PORTAL_ADMIN)")
|
||||
@RequestMapping(value = "/health_check/advanced", method = RequestMethod.GET)
|
||||
public ResponseEntity<Map<String, String>> checkEverything() {
|
||||
return ResponseEntity.ok(this.configuration.getProperties());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class ExceptionResponse {
|
||||
private final long timestamp;
|
||||
private final int status;
|
||||
private final String error;
|
||||
private final Class<?> exception;
|
||||
|
||||
public
|
||||
ExceptionResponse(Exception exception, HttpStatus status) {
|
||||
this.timestamp = new Date().getTime();
|
||||
this.status = status.value();
|
||||
this.error = exception.getMessage();
|
||||
this.exception = exception.getClass();
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public String getException() {
|
||||
return exception.getName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
@ControllerAdvice
|
||||
public class ExceptionsHandler {
|
||||
private final Logger log = LogManager.getLogger(this.getClass());
|
||||
|
||||
@ExceptionHandler(AccessDeniedException.class)
|
||||
public ResponseEntity<?> accessDenied(AccessDeniedException ex) {
|
||||
log.error(ex.getMessage(), ex);
|
||||
return new ResponseEntity<>(new ExceptionResponse(ex, HttpStatus.UNAUTHORIZED), HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpException.class)
|
||||
public ResponseEntity<?> http(HttpException ex) {
|
||||
log.error(ex.getMessage(), ex);
|
||||
return new ResponseEntity<>(new ExceptionResponse(ex, ex.getHttpStatus()), ex.getHttpStatus());
|
||||
}
|
||||
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public ResponseEntity<?> exception(RuntimeException ex) {
|
||||
log.error(ex.getMessage(), ex);
|
||||
return new ResponseEntity<>(new ExceptionResponse(ex, HttpStatus.BAD_REQUEST), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class HttpException extends RuntimeException {
|
||||
private final HttpStatus httpStatus;
|
||||
|
||||
public HttpException(String message, HttpStatus httpStatus) {
|
||||
super(message);
|
||||
this.httpStatus = httpStatus;
|
||||
}
|
||||
|
||||
public HttpStatus getHttpStatus() {
|
||||
return httpStatus;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.http;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.HttpException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class ConflictException extends HttpException {
|
||||
public ConflictException(String message){
|
||||
super(message, HttpStatus.CONFLICT);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.http;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.HttpException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class ForbiddenException extends HttpException {
|
||||
public ForbiddenException(String message){
|
||||
super(message, HttpStatus.FORBIDDEN); }
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.http;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.HttpException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class NotFoundException extends HttpException {
|
||||
public NotFoundException(String message){
|
||||
super(message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.http;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.HttpException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class UnauthorizedException extends HttpException {
|
||||
public UnauthorizedException(String message){
|
||||
super(message, HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.http;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.exceptions.HttpException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class UnprocessableException extends HttpException {
|
||||
public UnprocessableException(String message){
|
||||
super(message, HttpStatus.UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.redis;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.Redis;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.SecurityProperties;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.CheckProperties;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@Primary
|
||||
public class RedisCheckProperties implements CheckProperties {
|
||||
|
||||
@Override
|
||||
public void checkProperties(SecurityProperties properties) {
|
||||
Redis redis = properties.getRedis();
|
||||
if (redis.getHost() == null || redis.getHost().isEmpty()) {
|
||||
throw new RuntimeException("authorization.security.redis.host is missing!");
|
||||
} else if (redis.getPort() == null || redis.getPort().isEmpty()) {
|
||||
throw new RuntimeException("authorization.security.redis.port is missing!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getProperties(Map<String, String> map, SecurityProperties properties) {
|
||||
map.put("authorization.security.redis.host", properties.getRedis().getHost());
|
||||
map.put("authorization.security.redis.port", properties.getRedis().getPort());
|
||||
map.put("authorization.security.redis.password", properties.getRedis().getPassword());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.redis;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.SecurityProperties;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisIndexedHttpSession;
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
|
||||
@EnableRedisIndexedHttpSession(flushMode = FlushMode.IMMEDIATE, saveMode = SaveMode.ALWAYS)
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
private final SecurityProperties securityProperties;
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(RedisConfig.class);
|
||||
|
||||
@Autowired
|
||||
public RedisConfig(SecurityProperties securityProperties) {
|
||||
this.securityProperties = securityProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JedisConnectionFactory connectionFactory() {
|
||||
logger.info(String.format("Redis connection listens to %s:%s ", securityProperties.getRedis().getHost(), securityProperties.getRedis().getPort()));
|
||||
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(securityProperties.getRedis().getHost(), Integer.parseInt(securityProperties.getRedis().getPort()));
|
||||
if (securityProperties.getRedis().getPassword() != null)
|
||||
configuration.setPassword(securityProperties.getRedis().getPassword());
|
||||
return new JedisConnectionFactory(configuration);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate() {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory());
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setHashKeySerializer(new StringRedisSerializer());
|
||||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CookieSerializer cookieSerializer() {
|
||||
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
|
||||
serializer.setCookieName(securityProperties.getSession());
|
||||
serializer.setCookiePath("/");
|
||||
serializer.setDomainName(securityProperties.getDomain());
|
||||
return serializer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.redis;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.AuthorizationService;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.EntryPoint;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.SecurityMode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Primary
|
||||
public class RedisSecurityMode implements SecurityMode {
|
||||
|
||||
private final EntryPoint entryPoint;
|
||||
private final AuthorizationService service;
|
||||
|
||||
@Autowired
|
||||
public RedisSecurityMode(EntryPoint entryPoint, AuthorizationService service) {
|
||||
this.entryPoint = entryPoint;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSecurity security(HttpSecurity http) throws Exception {
|
||||
http.csrf(AbstractHttpConfigurer::disable);
|
||||
http.exceptionHandling(handler -> handler.authenticationEntryPoint(entryPoint));
|
||||
http.authorizeHttpRequests(auth -> auth.requestMatchers("/documentation/swagger-ui/**", "/v3/api-docs/**").hasAuthority(this.service.PORTAL_ADMIN).anyRequest().permitAll());
|
||||
return http;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,15 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.security;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.security;
|
||||
|
||||
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component(value = "AuthorizationService")
|
||||
|
@ -40,7 +42,7 @@ public class AuthorizationService {
|
|||
/**
|
||||
* Type = FUNDER | COMMUNITY | INSTITUTION | PROJECT
|
||||
*
|
||||
* Id = EE, EGI, etc
|
||||
* ID = EE, EGI, etc
|
||||
*/
|
||||
public String manager(String type, String id) {
|
||||
return mapType(type, true).toUpperCase() + "_" + id.toUpperCase() + "_MANAGER";
|
||||
|
@ -49,7 +51,7 @@ public class AuthorizationService {
|
|||
/**
|
||||
* Type = FUNDER | COMMUNITY | RI | INSTITUTION | PROJECT
|
||||
*
|
||||
* Id = EE, EGI, etc
|
||||
* ID = EE, EGI, etc
|
||||
*/
|
||||
public String member(String type, String id) {
|
||||
return mapType(type, false).toUpperCase() + "_" + id.toUpperCase();
|
||||
|
@ -85,7 +87,7 @@ public class AuthorizationService {
|
|||
if(authentication instanceof OpenAIREAuthentication) {
|
||||
return ((OpenAIREAuthentication) authentication).getUser().getSub();
|
||||
} else {
|
||||
return ((OIDCAuthenticationToken) authentication).getUserInfo().getSub();
|
||||
return Objects.requireNonNull(this.getOidcUser()).getSubject();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -97,7 +99,17 @@ public class AuthorizationService {
|
|||
if(authentication instanceof OpenAIREAuthentication) {
|
||||
return ((OpenAIREAuthentication) authentication).getUser().getEmail();
|
||||
} 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;
|
||||
|
@ -105,7 +117,7 @@ public class AuthorizationService {
|
|||
|
||||
private Authentication getAuthentication() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if(authentication instanceof OpenAIREAuthentication || authentication instanceof OIDCAuthenticationToken) {
|
||||
if(authentication instanceof OpenAIREAuthentication || authentication instanceof OAuth2AuthenticationToken) {
|
||||
return authentication;
|
||||
} else {
|
||||
return null;
|
|
@ -0,0 +1,12 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.security;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.SecurityProperties;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface CheckProperties {
|
||||
|
||||
void checkProperties(SecurityProperties securityProperties);
|
||||
|
||||
void getProperties(Map<String, String> map, SecurityProperties properties);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.security;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.SecurityProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
|
||||
private final SecurityProperties securityProperties;
|
||||
|
||||
@Autowired
|
||||
public CorsConfig(SecurityProperties securityProperties) {
|
||||
this.securityProperties = securityProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebMvcConfigurer corsConfigurer() {
|
||||
return new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOriginPatterns("*" + securityProperties.getDomain(), "*" + securityProperties.getDomain() + ":*")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
|
||||
.allowCredentials(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.security;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.security;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class EntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
@Override
|
|
@ -1,6 +1,6 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.security;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.security;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.stateless.utils.UserInfo;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.stateless.UserInfo;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
|
||||
public class OpenAIREAuthentication extends AbstractAuthenticationToken {
|
|
@ -0,0 +1,8 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.security;
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
||||
public interface SecurityMode {
|
||||
|
||||
HttpSecurity security(HttpSecurity http) throws Exception;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.stateless;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.OpenAIREAuthentication;
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class AuthorizationFilter implements Filter {
|
||||
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
|
||||
AuthorizationFilter(AuthorizationProvider authorizationProvider) {
|
||||
this.authorizationProvider = authorizationProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
if (request instanceof HttpServletRequest req) {
|
||||
OpenAIREAuthentication auth = authorizationProvider.getAuthentication(req);
|
||||
if (auth.isAuthenticated()) {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
|
@ -1,13 +1,10 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.stateless.security;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.stateless;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.security.OpenAIREAuthentication;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.stateless.utils.AuthorizationUtils;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.stateless.utils.UserInfo;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.OpenAIREAuthentication;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Component
|
||||
public class AuthorizationProvider {
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.stateless.utils;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.stateless;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.configuration.SecurityConfig;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.SecurityProperties;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -9,24 +11,23 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
@Component
|
||||
public class AuthorizationUtils {
|
||||
private final Logger log = LogManager.getLogger(this.getClass());
|
||||
private final SecurityConfig securityConfig;
|
||||
private final SecurityProperties securityProperties;
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
AuthorizationUtils(SecurityConfig securityConfig) {
|
||||
this.securityConfig = securityConfig;
|
||||
AuthorizationUtils(SecurityProperties securityProperties, RestTemplate restTemplate) {
|
||||
this.securityProperties = securityProperties;
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
public UserInfo getUserInfo(HttpServletRequest request) {
|
||||
String url = securityConfig.getUserInfoUrl();
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
String url = securityProperties.getUserInfoUrl();
|
||||
try {
|
||||
if(url != null && hasCookie(request)) {
|
||||
ResponseEntity<UserInfo> response = restTemplate.exchange(url, HttpMethod.GET, createHeaders(request), UserInfo.class);
|
||||
|
@ -34,7 +35,7 @@ public class AuthorizationUtils {
|
|||
}
|
||||
return null;
|
||||
} catch (RestClientException e) {
|
||||
log.error(url + ": " + e.getMessage());
|
||||
log.error("{}: {}", url, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +43,7 @@ public class AuthorizationUtils {
|
|||
private boolean hasCookie(HttpServletRequest request) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if(cookies != null) {
|
||||
return Arrays.stream(cookies).anyMatch(cookie -> cookie.getName().equalsIgnoreCase(this.securityConfig.getSession()));
|
||||
return Arrays.stream(cookies).anyMatch(cookie -> cookie.getName().equalsIgnoreCase(this.securityProperties.getSession()));
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.stateless;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.configuration.SecurityProperties;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.CheckProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class StatelessCheckProperties implements CheckProperties {
|
||||
|
||||
@Override
|
||||
public void checkProperties(SecurityProperties properties) {
|
||||
if(properties.getUserInfoUrl() == null || properties.getUserInfoUrl().isEmpty()) {
|
||||
throw new RuntimeException("authorization.security.userInfoUrl is missing!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getProperties(Map<String, String> map, SecurityProperties properties) {
|
||||
map.put("authorization.security.userInfoUrl", properties.getUserInfoUrl());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.authorization.stateless;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.AuthorizationService;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.EntryPoint;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.authorization.security.SecurityMode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StatelessSecurityMode implements SecurityMode {
|
||||
|
||||
private final AuthorizationProvider provider;
|
||||
private final EntryPoint entryPoint;
|
||||
private final AuthorizationService service;
|
||||
|
||||
@Autowired
|
||||
public StatelessSecurityMode(AuthorizationProvider provider, EntryPoint entryPoint, AuthorizationService service) {
|
||||
this.provider = provider;
|
||||
this.entryPoint = entryPoint;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSecurity security(HttpSecurity http) throws Exception {
|
||||
http.csrf(AbstractHttpConfigurer::disable);
|
||||
http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
||||
http.addFilterBefore(new AuthorizationFilter(this.provider), BasicAuthenticationFilter.class);
|
||||
http.exceptionHandling(handler -> handler.authenticationEntryPoint(entryPoint));
|
||||
http.authorizeHttpRequests(auth -> auth.requestMatchers("/documentation/swagger-ui/**", "/v3/api-docs/**").hasAuthority(this.service.PORTAL_ADMIN).anyRequest().permitAll());
|
||||
return http;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.stateless.utils;
|
||||
package eu.dnetlib.uoaauthorizationlibrary.authorization.stateless;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
@ -1,25 +0,0 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.configuration;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({SecurityConfig.class, GlobalVars.class})
|
||||
@ComponentScan(basePackages = { "eu.dnetlib.uoaauthorizationlibrary" })
|
||||
public class AuthorizationConfiguration {
|
||||
|
||||
@Bean
|
||||
public WebMvcConfigurer corsConfigurer() {
|
||||
return new WebMvcConfigurerAdapter() {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
|
||||
.allowCredentials(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.configuration;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.security.AuthorizationService;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(
|
||||
basePackageClasses = {AuthorizationService.class}
|
||||
)
|
||||
public class IgnoreSecurityConfiguration {
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.controllers;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.configuration.GlobalVars;
|
||||
import eu.dnetlib.uoaauthorizationlibrary.configuration.SecurityConfig;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(origins = "*")
|
||||
@RequestMapping("/authorization-library")
|
||||
public class AuthorizationLibraryCheckDeployController {
|
||||
private final Logger log = LogManager.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private SecurityConfig securityConfig;
|
||||
|
||||
@Autowired
|
||||
private GlobalVars globalVars;
|
||||
|
||||
@RequestMapping(value = {"", "/health_check"}, method = RequestMethod.GET)
|
||||
public String hello() {
|
||||
log.debug("Hello from uoa-authorization-library!");
|
||||
return "Hello from uoa-authorization-library!";
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyAuthority(@AuthorizationService.PORTAL_ADMIN)")
|
||||
@RequestMapping(value = "/health_check/advanced", method = RequestMethod.GET)
|
||||
public Map<String, String> checkEverything() {
|
||||
Map<String, String> response = new HashMap<>();
|
||||
response.put("authorization.security.redis.host", securityConfig.getRedis().getHost());
|
||||
response.put("authorization.security.userInfoUrl", securityConfig.getUserInfoUrl());
|
||||
response.put("authorization.security.session", securityConfig.getSession());
|
||||
response.put("authorization.security.domain", securityConfig.getDomain());
|
||||
if(GlobalVars.date != null) {
|
||||
response.put("Date of deploy", GlobalVars.date.toString());
|
||||
}
|
||||
if(globalVars.getBuildDate() != null) {
|
||||
response.put("Date of build", globalVars.getBuildDate());
|
||||
}
|
||||
if (globalVars.getVersion() != null) {
|
||||
response.put("Version", globalVars.getVersion());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.redis.configuration;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.configuration.SecurityConfig;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
private final SecurityConfig securityConfig;
|
||||
private static final Logger logger = LogManager.getLogger(RedisConfig.class);
|
||||
|
||||
@Autowired
|
||||
public RedisConfig(SecurityConfig securityConfig) {this.securityConfig = securityConfig;}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory connectionFactory() {
|
||||
logger.info(String.format("Redis connection listens to %s:%s ", securityConfig.getRedis().getHost(), securityConfig.getRedis().getPort()));
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(securityConfig.getRedis().getHost(), Integer.parseInt(securityConfig.getRedis().getPort()));
|
||||
if (securityConfig.getRedis().getPassword() != null) factory.setPassword(securityConfig.getRedis().getPassword());
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CookieSerializer cookieSerializer() {
|
||||
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
|
||||
serializer.setCookieName(securityConfig.getSession());
|
||||
serializer.setCookiePath("/");
|
||||
serializer.setDomainName(securityConfig.getDomain());
|
||||
return serializer;
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.redis.security;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.security.EntryPoint;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
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.WebSecurityConfigurerAdapter;
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.csrf().disable();
|
||||
http.authorizeRequests().anyRequest().permitAll();
|
||||
http.httpBasic().authenticationEntryPoint(new EntryPoint());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.stateless.security;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.security.OpenAIREAuthentication;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class AuthorizationFilter implements Filter {
|
||||
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
|
||||
@Autowired
|
||||
AuthorizationFilter(AuthorizationProvider authorizationProvider) {
|
||||
this.authorizationProvider = authorizationProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
|
||||
OpenAIREAuthentication auth = authorizationProvider.getAuthentication((HttpServletRequest) req);
|
||||
if(auth.isAuthenticated()) {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
filterChain.doFilter(req, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package eu.dnetlib.uoaauthorizationlibrary.stateless.security;
|
||||
|
||||
import eu.dnetlib.uoaauthorizationlibrary.security.EntryPoint;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
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.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final AuthorizationFilter filter;
|
||||
|
||||
@Autowired
|
||||
WebSecurityConfig(AuthorizationFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.apply(new AuthorizationFilterConfigurer(filter));
|
||||
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
http.authorizeRequests().anyRequest().permitAll();
|
||||
http.httpBasic().authenticationEntryPoint(new EntryPoint());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
#dev
|
||||
spring.session.store-type=none
|
||||
authorization.security.userInfoUrl=
|
||||
authorization.security.domain=di.uoa.gr
|
||||
authorization.security.session=openAIRESession
|
||||
authorization.global-vars.buildDate=@timestampAuthorizationLibrary@
|
||||
authorization.global-vars.version=@project.version@
|
||||
|
||||
springdoc.swagger-ui.path=/documentation/swagger-ui
|
||||
|
|
Loading…
Reference in New Issue