diff --git a/pom.xml b/pom.xml
index 83ff017..a10c2fc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,6 @@
dnet45-parent
1.0.0
- eu.dnetlinb
login-service
0.0.1-SNAPSHOT
war
@@ -33,6 +32,11 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
org.springframework.boot
spring-boot-starter-tomcat
@@ -69,24 +73,6 @@
-
-
- com.google.code.gson
- gson
- 2.6.2
-
-
-
- io.springfox
- springfox-swagger2
- 2.7.0
-
-
-
- io.springfox
- springfox-swagger-ui
- 2.7.0
-
diff --git a/src/main/java/eu/dnetlib/loginservice/LoginServiceApplication.java b/src/main/java/eu/dnetlib/loginservice/LoginServiceApplication.java
new file mode 100644
index 0000000..a0dde7b
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/LoginServiceApplication.java
@@ -0,0 +1,22 @@
+package eu.dnetlib.loginservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.annotation.PropertySources;
+import eu.dnetlib.loginservice.properties.Properties;
+
+@SpringBootApplication(scanBasePackages = {"eu.dnetlib.loginservice"})
+@PropertySources({
+ @PropertySource("classpath:application.properties"),
+ @PropertySource(value = "classpath:dnet-override.properties", ignoreResourceNotFound = true)
+})
+@EnableConfigurationProperties({Properties.class})
+public class LoginServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(LoginServiceApplication.class, args);
+ }
+
+}
diff --git a/src/main/java/eu/dnetlinb/loginservice/ServletInitializer.java b/src/main/java/eu/dnetlib/loginservice/ServletInitializer.java
similarity index 92%
rename from src/main/java/eu/dnetlinb/loginservice/ServletInitializer.java
rename to src/main/java/eu/dnetlib/loginservice/ServletInitializer.java
index 09a249f..faf52ff 100644
--- a/src/main/java/eu/dnetlinb/loginservice/ServletInitializer.java
+++ b/src/main/java/eu/dnetlib/loginservice/ServletInitializer.java
@@ -1,4 +1,4 @@
-package eu.dnetlinb.loginservice;
+package eu.dnetlib.loginservice;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
diff --git a/src/main/java/eu/dnetlib/loginservice/controllers/HealthController.java b/src/main/java/eu/dnetlib/loginservice/controllers/HealthController.java
new file mode 100644
index 0000000..fb7d4d0
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/controllers/HealthController.java
@@ -0,0 +1,17 @@
+package eu.dnetlib.loginservice.controllers;
+
+import org.apache.log4j.Logger;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class HealthController {
+ private final Logger log = Logger.getLogger(this.getClass());
+
+ @RequestMapping(value = {"", "/health_check"}, method = RequestMethod.GET)
+ public String hello() {
+ log.debug("Hello from Login service!");
+ return "Hello from Login service!";
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/controllers/UserController.java b/src/main/java/eu/dnetlib/loginservice/controllers/UserController.java
new file mode 100644
index 0000000..3ada99c
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/controllers/UserController.java
@@ -0,0 +1,22 @@
+package eu.dnetlib.loginservice.controllers;
+
+import eu.dnetlib.loginservice.entities.User;
+import eu.dnetlib.loginservice.exception.ResourceNotFoundException;
+import org.mitre.openid.connect.model.OIDCAuthenticationToken;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class UserController {
+
+ @RequestMapping(value = "/userInfo", method = RequestMethod.GET)
+ public ResponseEntity getUserInfo(Authentication authentication) {
+ if(authentication instanceof OIDCAuthenticationToken) {
+ return ResponseEntity.ok(new User((OIDCAuthenticationToken) authentication));
+ }
+ throw new ResourceNotFoundException("No Session has been found");
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/entities/User.java b/src/main/java/eu/dnetlib/loginservice/entities/User.java
new file mode 100644
index 0000000..ca459d1
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/entities/User.java
@@ -0,0 +1,74 @@
+package eu.dnetlib.loginservice.entities;
+
+import org.mitre.openid.connect.model.OIDCAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class User {
+
+ private String sub;
+ private String name;
+ private String given_name;
+ private String family_name;
+ private String email;
+ private Set roles;
+
+ public User(OIDCAuthenticationToken token) {
+ this.sub = token.getUserInfo().getSub();
+ this.name = token.getUserInfo().getName();
+ this.given_name = token.getUserInfo().getGivenName();
+ this.family_name = token.getUserInfo().getFamilyName();
+ this.email = token.getUserInfo().getEmail();
+ this.roles = token.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
+ }
+
+ public String getSub() {
+ return sub;
+ }
+
+ public void setSub(String sub) {
+ this.sub = sub;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getGiven_name() {
+ return given_name;
+ }
+
+ public void setGiven_name(String given_name) {
+ this.given_name = given_name;
+ }
+
+ public String getFamily_name() {
+ return family_name;
+ }
+
+ public void setFamily_name(String family_name) {
+ this.family_name = family_name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public Set getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set roles) {
+ this.roles = roles;
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/exception/ResourceNotFoundException.java b/src/main/java/eu/dnetlib/loginservice/exception/ResourceNotFoundException.java
new file mode 100644
index 0000000..dfff6f8
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/exception/ResourceNotFoundException.java
@@ -0,0 +1,20 @@
+package eu.dnetlib.loginservice.exception;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(value = HttpStatus.NOT_FOUND) // 404
+public class ResourceNotFoundException extends RuntimeException {
+
+ public ResourceNotFoundException(String message) {
+ super(message);
+ }
+
+ public ResourceNotFoundException(String message, Throwable err) {
+ super(message, err);
+ }
+
+ public HttpStatus getStatus() {
+ return HttpStatus.NOT_FOUND;
+ }
+}
+
diff --git a/src/main/java/eu/dnetlib/loginservice/properties/OIDC.java b/src/main/java/eu/dnetlib/loginservice/properties/OIDC.java
new file mode 100644
index 0000000..114a036
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/properties/OIDC.java
@@ -0,0 +1,59 @@
+package eu.dnetlib.loginservice.properties;
+
+public class OIDC {
+
+ private String issuer;
+ private String home;
+ private String id;
+ private String secret;
+ private String scope = "";
+ private String logout;
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ public void setIssuer(String issuer) {
+ this.issuer = issuer;
+ }
+
+ public String getHome() {
+ return home;
+ }
+
+ public void setHome(String home) {
+ this.home = home;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getSecret() {
+ return secret;
+ }
+
+ public void setSecret(String secret) {
+ this.secret = secret;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+
+ public String getLogout() {
+ return logout;
+ }
+
+ public void setLogout(String logout) {
+ this.logout = logout;
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/properties/Properties.java b/src/main/java/eu/dnetlib/loginservice/properties/Properties.java
new file mode 100644
index 0000000..8632ed3
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/properties/Properties.java
@@ -0,0 +1,56 @@
+package eu.dnetlib.loginservice.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties("authentication")
+public class Properties {
+
+ private Redis redis = new Redis();
+ private OIDC oidc = new OIDC();
+ private String domain;
+ private String session;
+ private String redirect;
+
+ public Properties() {
+ }
+
+ public Redis getRedis() {
+ return redis;
+ }
+
+ public void setRedis(Redis redis) {
+ this.redis = redis;
+ }
+
+ public OIDC getOidc() {
+ return oidc;
+ }
+
+ public void setOidc(OIDC oidc) {
+ this.oidc = oidc;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public void setDomain(String domain) {
+ this.domain = domain;
+ }
+
+ public String getSession() {
+ return session;
+ }
+
+ public void setSession(String session) {
+ this.session = session;
+ }
+
+ public String getRedirect() {
+ return redirect;
+ }
+
+ public void setRedirect(String redirect) {
+ this.redirect = redirect;
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/properties/Redis.java b/src/main/java/eu/dnetlib/loginservice/properties/Redis.java
new file mode 100644
index 0000000..5ff24a4
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/properties/Redis.java
@@ -0,0 +1,44 @@
+package eu.dnetlib.loginservice.properties;
+
+public class Redis {
+
+ private String host = "localhost";
+ private String port = "6379";
+ private String password;
+
+ public Redis() {
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ @Override
+ public String toString() {
+ return "Redis{" +
+ "host='" + host + '\'' +
+ ", port='" + port + '\'' +
+ ", password='" + password + '\'' +
+ '}';
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/CorsConfig.java b/src/main/java/eu/dnetlib/loginservice/security/CorsConfig.java
new file mode 100644
index 0000000..230e4d1
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/CorsConfig.java
@@ -0,0 +1,16 @@
+package eu.dnetlib.loginservice.security;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@Configuration
+public class CorsConfig extends WebMvcConfigurerAdapter {
+
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ registry.addMapping("/**")
+ .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
+ .allowCredentials(true);
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/RedisConfig.java b/src/main/java/eu/dnetlib/loginservice/security/RedisConfig.java
new file mode 100644
index 0000000..20fe0a5
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/RedisConfig.java
@@ -0,0 +1,42 @@
+package eu.dnetlib.loginservice.security;
+
+import eu.dnetlib.loginservice.properties.Properties;
+import org.apache.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 Properties properties;
+
+ private static final Logger logger = Logger.getLogger(RedisConfig.class);
+
+ @Autowired
+ public RedisConfig(Properties properties) {
+ this.properties = properties;
+ }
+
+ @Bean
+ public LettuceConnectionFactory connectionFactory() {
+ logger.info(String.format("Redis connection listens to %s:%s ", properties.getRedis().getHost(), properties.getRedis().getPort()));
+ LettuceConnectionFactory factory = new LettuceConnectionFactory(properties.getRedis().getHost(), Integer.parseInt(properties.getRedis().getPort()));
+ if (properties.getRedis().getPassword() != null) factory.setPassword(properties.getRedis().getPassword());
+ return factory;
+ }
+
+ @Bean
+ public CookieSerializer cookieSerializer() {
+ DefaultCookieSerializer serializer = new DefaultCookieSerializer();
+ serializer.setCookieName(properties.getSession());
+ serializer.setCookiePath("/");
+ serializer.setDomainName(properties.getDomain());
+ return serializer;
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/WebSecurityConfig.java b/src/main/java/eu/dnetlib/loginservice/security/WebSecurityConfig.java
new file mode 100644
index 0000000..1277c0c
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/WebSecurityConfig.java
@@ -0,0 +1,82 @@
+package eu.dnetlib.loginservice.security;
+
+import eu.dnetlib.loginservice.properties.Properties;
+import eu.dnetlib.loginservice.security.oidc.OpenAIREAuthenticationFilter;
+import eu.dnetlib.loginservice.security.oidc.OpenAIREAuthenticationSuccessHandler;
+import eu.dnetlib.loginservice.security.oidc.OpenAIRELogoutHandler;
+import eu.dnetlib.loginservice.security.oidc.OpenAIRELogoutSuccessHandler;
+import eu.dnetlib.loginservice.utils.EntryPoint;
+import org.mitre.openid.connect.client.OIDCAuthenticationProvider;
+import org.mitre.openid.connect.client.service.ClientConfigurationService;
+import org.mitre.openid.connect.client.service.IssuerService;
+import org.mitre.openid.connect.client.service.ServerConfigurationService;
+import org.mitre.openid.connect.client.service.impl.PlainAuthRequestUrlBuilder;
+import org.mitre.openid.connect.client.service.impl.StaticAuthRequestOptionsService;
+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.web.authentication.www.BasicAuthenticationFilter;
+
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ private final Properties properties;
+ private final EntryPoint entryPoint;
+ private final OIDCAuthenticationProvider provider;
+ private final IssuerService issuerService;
+ private final ServerConfigurationService serverConfigurationService;
+ private final ClientConfigurationService clientConfigurationService;
+ private final StaticAuthRequestOptionsService optionsService;
+ private final PlainAuthRequestUrlBuilder builder;
+ private final OpenAIREAuthenticationSuccessHandler authenticationSuccessHandler;
+ private final OpenAIRELogoutHandler logoutHandler;
+ private final OpenAIRELogoutSuccessHandler logoutSuccessHandler;
+
+ @Autowired
+ public WebSecurityConfig(Properties properties, EntryPoint entryPoint, OIDCAuthenticationProvider provider,
+ IssuerService issuerService, ServerConfigurationService serverConfigurationService,
+ ClientConfigurationService clientConfigurationService, StaticAuthRequestOptionsService optionsService,
+ PlainAuthRequestUrlBuilder builder, OpenAIREAuthenticationSuccessHandler authenticationSuccessHandler,
+ OpenAIRELogoutHandler logoutHandler, OpenAIRELogoutSuccessHandler logoutSuccessHandler) {
+ super();
+ this.properties = properties;
+ this.entryPoint = entryPoint;
+ this.provider = provider;
+ this.issuerService = issuerService;
+ this.serverConfigurationService = serverConfigurationService;
+ this.clientConfigurationService = clientConfigurationService;
+ this.optionsService = optionsService;
+ this.builder = builder;
+ this.authenticationSuccessHandler = authenticationSuccessHandler;
+ this.logoutHandler = logoutHandler;
+ this.logoutSuccessHandler = logoutSuccessHandler;
+ }
+
+ public OpenAIREAuthenticationFilter initFilter() throws Exception {
+ OpenAIREAuthenticationFilter filter = new OpenAIREAuthenticationFilter(properties);
+ filter.setAuthenticationManager(authenticationManagerBean());
+ filter.afterPropertiesSet();
+ filter.setIssuerService(issuerService);
+ filter.setServerConfigurationService(serverConfigurationService);
+ filter.setClientConfigurationService(clientConfigurationService);
+ filter.setAuthRequestOptionsService(optionsService);
+ filter.setAuthRequestUrlBuilder(builder);
+ filter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
+ return filter;
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.csrf().disable();
+ http.authenticationProvider(provider);
+ http.addFilterBefore(initFilter(), BasicAuthenticationFilter.class);
+ http.httpBasic().authenticationEntryPoint(entryPoint);
+ http.logout().logoutUrl("/openid_logout").addLogoutHandler(logoutHandler)
+ .logoutSuccessHandler(logoutSuccessHandler).invalidateHttpSession(false);
+ http.authorizeRequests().anyRequest().permitAll();
+ }
+
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Configurations.java b/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Configurations.java
new file mode 100644
index 0000000..cf11f81
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Configurations.java
@@ -0,0 +1,49 @@
+package eu.dnetlib.loginservice.security.initiliazers;
+
+import eu.dnetlib.loginservice.properties.Properties;
+import eu.dnetlib.loginservice.utils.ScopeReader;
+import org.mitre.oauth2.model.ClientDetailsEntity;
+import org.mitre.oauth2.model.RegisteredClient;
+import org.mitre.openid.connect.config.ServerConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Collections;
+
+@Configuration
+public class Configurations {
+
+ private final Properties properties;
+ private final ScopeReader scopeReader;
+
+ @Autowired
+ public Configurations(Properties properties, ScopeReader scopeReader) {
+ this.properties = properties;
+ this.scopeReader = scopeReader;
+ }
+
+ @Bean
+ public ServerConfiguration serverConfiguration() {
+ String issuer = properties.getOidc().getIssuer();
+ ServerConfiguration serverConfiguration = new ServerConfiguration();
+ serverConfiguration.setIssuer(issuer);
+ serverConfiguration.setAuthorizationEndpointUri(issuer + "authorize");
+ serverConfiguration.setTokenEndpointUri(issuer + "token");
+ serverConfiguration.setUserInfoUri(issuer + "userinfo");
+ serverConfiguration.setJwksUri(issuer + "jwk");
+ serverConfiguration.setRevocationEndpointUri(issuer + "revoke");
+ return serverConfiguration;
+ }
+
+ @Bean
+ public RegisteredClient registeredClient() {
+ RegisteredClient client = new RegisteredClient();
+ client.setClientId(properties.getOidc().getId());
+ client.setClientSecret(properties.getOidc().getSecret());
+ client.setScope(scopeReader.getScopes());
+ client.setTokenEndpointAuthMethod(ClientDetailsEntity.AuthMethod.SECRET_BASIC);
+ client.setRedirectUris(Collections.singleton(properties.getOidc().getHome()));
+ return client;
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Primitives.java b/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Primitives.java
new file mode 100644
index 0000000..b1f82bf
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Primitives.java
@@ -0,0 +1,68 @@
+package eu.dnetlib.loginservice.security.initiliazers;
+
+import eu.dnetlib.loginservice.properties.Properties;
+import eu.dnetlib.loginservice.security.oidc.OpenAIREAuthoritiesMapper;
+import eu.dnetlib.loginservice.utils.EntryPoint;
+import eu.dnetlib.loginservice.utils.ScopeReader;
+import org.mitre.openid.connect.client.OIDCAuthenticationFilter;
+import org.mitre.openid.connect.client.OIDCAuthenticationProvider;
+import org.mitre.openid.connect.client.service.impl.PlainAuthRequestUrlBuilder;
+import org.mitre.openid.connect.client.service.impl.StaticAuthRequestOptionsService;
+import org.mitre.openid.connect.client.service.impl.StaticSingleIssuerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
+import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
+
+@Configuration
+public class Primitives {
+
+ private final Properties properties;
+ private final OpenAIREAuthoritiesMapper authoritiesMapper;;
+
+ @Autowired
+ public Primitives(Properties properties, OpenAIREAuthoritiesMapper authoritiesMapper) {
+ this.properties = properties;
+ this.authoritiesMapper = authoritiesMapper;
+ }
+
+ @Bean
+ public ScopeReader scopeReader() {
+ return new ScopeReader(this.properties.getOidc().getScope());
+ }
+
+ @Bean
+ public DefaultWebSecurityExpressionHandler handler() {
+ return new DefaultWebSecurityExpressionHandler();
+ }
+
+ @Bean
+ public PlainAuthRequestUrlBuilder builder() {
+ return new PlainAuthRequestUrlBuilder();
+ }
+
+ @Bean
+ public OIDCAuthenticationProvider provider() {
+ OIDCAuthenticationProvider provider = new OIDCAuthenticationProvider();
+ provider.setAuthoritiesMapper(authoritiesMapper);
+ return provider;
+ }
+
+ @Bean
+ public StaticSingleIssuerService issuerService() {
+ StaticSingleIssuerService issuerService = new StaticSingleIssuerService();
+ issuerService.setIssuer(properties.getOidc().getIssuer());
+ return issuerService;
+ }
+
+ @Bean
+ public EntryPoint entryPoint() {
+ return new EntryPoint();
+ }
+
+ @Bean
+ public StaticAuthRequestOptionsService optionsService() {
+ return new StaticAuthRequestOptionsService();
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Services.java b/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Services.java
new file mode 100644
index 0000000..ab48d75
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/initiliazers/Services.java
@@ -0,0 +1,48 @@
+package eu.dnetlib.loginservice.security.initiliazers;
+
+import eu.dnetlib.loginservice.properties.Properties;
+import eu.dnetlib.loginservice.utils.ScopeReader;
+import org.mitre.oauth2.model.RegisteredClient;
+import org.mitre.openid.connect.client.service.impl.StaticClientConfigurationService;
+import org.mitre.openid.connect.client.service.impl.StaticServerConfigurationService;
+import org.mitre.openid.connect.config.ServerConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class Services {
+
+ private final Properties properties;
+ private final ServerConfiguration serverConfiguration;
+ private final RegisteredClient clientConfiguration;
+
+ @Autowired
+ public Services(Properties properties, ServerConfiguration serverConfiguration, RegisteredClient clientConfiguration) {
+ this.properties = properties;
+ this.serverConfiguration = serverConfiguration;
+ this.clientConfiguration = clientConfiguration;
+ }
+
+
+ @Bean
+ public StaticServerConfigurationService serverConfigurationService() {
+ StaticServerConfigurationService configurationService = new StaticServerConfigurationService();
+ Map servers = new HashMap<>();
+ servers.put(properties.getOidc().getIssuer(), serverConfiguration);
+ configurationService.setServers(servers);
+ return configurationService;
+ }
+
+ @Bean
+ public StaticClientConfigurationService clientConfigurationService() {
+ StaticClientConfigurationService configurationService = new StaticClientConfigurationService();
+ Map clients = new HashMap<>();
+ clients.put(properties.getOidc().getIssuer(), clientConfiguration);
+ configurationService.setClients(clients);
+ return configurationService;
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthenticationFilter.java b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthenticationFilter.java
new file mode 100644
index 0000000..5fd35fa
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthenticationFilter.java
@@ -0,0 +1,27 @@
+package eu.dnetlib.loginservice.security.oidc;
+
+import eu.dnetlib.loginservice.properties.Properties;
+import eu.dnetlib.loginservice.utils.Redirect;
+import org.apache.log4j.Logger;
+import org.mitre.openid.connect.client.OIDCAuthenticationFilter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class OpenAIREAuthenticationFilter extends OIDCAuthenticationFilter {
+
+ private final static Logger logger = Logger.getLogger(OpenAIREAuthenticationSuccessHandler.class);
+ private final Properties properties;
+
+ public OpenAIREAuthenticationFilter(Properties properties) {
+ super();
+ this.properties = properties;
+ }
+
+ @Override
+ protected void handleAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ Redirect.setRedirect(request, properties);
+ super.handleAuthorizationRequest(request, response);
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthenticationSuccessHandler.java b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthenticationSuccessHandler.java
new file mode 100644
index 0000000..7b50015
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthenticationSuccessHandler.java
@@ -0,0 +1,65 @@
+package eu.dnetlib.loginservice.security.oidc;
+
+import com.google.gson.JsonParser;
+import eu.dnetlib.loginservice.properties.Properties;
+import org.apache.log4j.Logger;
+import org.mitre.openid.connect.model.OIDCAuthenticationToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.session.FindByIndexNameSessionRepository;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.Base64;
+import java.util.Date;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Configuration
+public class OpenAIREAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
+
+ private static final Logger logger = Logger.getLogger(OpenAIREAuthenticationSuccessHandler.class);
+ private final Properties properties;
+
+ @Autowired
+ public OpenAIREAuthenticationSuccessHandler(Properties properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+ throws IOException {
+ OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication;
+ HttpSession session = request.getSession();
+ String redirect = (String) session.getAttribute("redirect");
+ session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, token.getUserInfo().getSub());
+ try {
+ Cookie accessToken = new Cookie("AccessToken", token.getAccessTokenValue());
+ String regex = "^([A-Za-z0-9-_=]+)\\.([A-Za-z0-9-_=]+)\\.?([A-Za-z0-9-_.+=]*)$";
+ Matcher matcher = Pattern.compile(regex).matcher(token.getAccessTokenValue());
+ if (matcher.find()) {
+ long exp = new JsonParser().parse(new String(Base64.getDecoder().decode(matcher.group(2)))).getAsJsonObject().get("exp").getAsLong();
+ accessToken.setMaxAge((int) (exp - (new Date().getTime() / 1000)));
+ } else {
+ accessToken.setMaxAge(3600);
+ }
+ accessToken.setPath("/");
+ accessToken.setDomain(properties.getDomain());
+ response.addCookie(accessToken);
+ if(redirect != null) {
+ response.sendRedirect(redirect);
+ session.removeAttribute("redirect");
+ } else {
+ response.sendRedirect(properties.getRedirect());
+ }
+ } catch (IOException e) {
+ logger.error("IOException in redirection ", e);
+ throw new IOException(e);
+ }
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthoritiesMapper.java b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthoritiesMapper.java
new file mode 100644
index 0000000..29d7cf9
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIREAuthoritiesMapper.java
@@ -0,0 +1,21 @@
+package eu.dnetlib.loginservice.security.oidc;
+
+import com.google.gson.JsonArray;
+import com.nimbusds.jwt.JWT;
+import eu.dnetlib.loginservice.utils.AuthoritiesMapper;
+import org.mitre.openid.connect.client.OIDCAuthoritiesMapper;
+import org.mitre.openid.connect.model.UserInfo;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+
+@Component
+public class OpenAIREAuthoritiesMapper implements OIDCAuthoritiesMapper {
+
+ @Override
+ public Collection extends GrantedAuthority> mapAuthorities(JWT jwtToken, UserInfo userInfo) {
+ JsonArray entitlements = userInfo.getSource().getAsJsonArray("edu_person_entitlements");
+ return AuthoritiesMapper.map(entitlements);
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIRELogoutHandler.java b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIRELogoutHandler.java
new file mode 100644
index 0000000..9285554
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIRELogoutHandler.java
@@ -0,0 +1,27 @@
+package eu.dnetlib.loginservice.security.oidc;
+
+import eu.dnetlib.loginservice.properties.Properties;
+import eu.dnetlib.loginservice.utils.Redirect;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutHandler;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Service
+public class OpenAIRELogoutHandler implements LogoutHandler {
+
+ private Properties properties;
+
+ @Autowired
+ public OpenAIRELogoutHandler(Properties properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
+ Redirect.setRedirect(request, properties);
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIRELogoutSuccessHandler.java b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIRELogoutSuccessHandler.java
new file mode 100644
index 0000000..f42afa7
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/security/oidc/OpenAIRELogoutSuccessHandler.java
@@ -0,0 +1,37 @@
+package eu.dnetlib.loginservice.security.oidc;
+
+import eu.dnetlib.loginservice.properties.Properties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+@Configuration
+public class OpenAIRELogoutSuccessHandler implements LogoutSuccessHandler {
+
+ private final Properties properties;
+
+ @Autowired
+ public OpenAIRELogoutSuccessHandler(Properties properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
+ HttpSession session = request.getSession();
+ String redirect = (String) session.getAttribute("redirect");
+ session.removeAttribute("redirect");
+ if(redirect == null) {
+ redirect = properties.getRedirect();
+ }
+ session.invalidate();
+ response.sendRedirect(properties.getOidc().getLogout() + redirect);
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/utils/AuthoritiesMapper.java b/src/main/java/eu/dnetlib/loginservice/utils/AuthoritiesMapper.java
new file mode 100644
index 0000000..da9321e
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/utils/AuthoritiesMapper.java
@@ -0,0 +1,41 @@
+package eu.dnetlib.loginservice.utils;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import org.apache.log4j.Logger;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class AuthoritiesMapper {
+
+ private static final Logger logger = Logger.getLogger(AuthoritiesMapper.class);
+
+ public static Collection extends GrantedAuthority> map(JsonArray entitlements) {
+ HashSet authorities = new HashSet<>();
+ String regex = "urn:geant:openaire[.]eu:group:([^:]*):?(.*)?:role=member#aai[.]openaire[.]eu";
+ for(JsonElement obj: entitlements) {
+ Matcher matcher = Pattern.compile(regex).matcher(obj.getAsString());
+ if (matcher.find()) {
+ StringBuilder sb = new StringBuilder();
+ if(matcher.group(1) != null && matcher.group(1).length() > 0) {
+ sb.append(matcher.group(1).replace("+-+", "_").replaceAll("[+.]", "_").toUpperCase());
+ }
+ if(matcher.group(2).length() > 0) {
+ sb.append("_");
+ if(matcher.group(2).equals("admins")) {
+ sb.append("MANAGER");
+ } else {
+ sb.append(matcher.group(2).toUpperCase());
+ }
+ }
+ authorities.add(new SimpleGrantedAuthority(sb.toString()));
+ }
+ }
+ return authorities;
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/utils/EntryPoint.java b/src/main/java/eu/dnetlib/loginservice/utils/EntryPoint.java
new file mode 100644
index 0000000..cbd5538
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/utils/EntryPoint.java
@@ -0,0 +1,19 @@
+package eu.dnetlib.loginservice.utils;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class EntryPoint implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException authException) throws IOException {
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
+ }
+
+}
+
diff --git a/src/main/java/eu/dnetlib/loginservice/utils/Redirect.java b/src/main/java/eu/dnetlib/loginservice/utils/Redirect.java
new file mode 100644
index 0000000..909fd81
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/utils/Redirect.java
@@ -0,0 +1,39 @@
+package eu.dnetlib.loginservice.utils;
+
+
+import eu.dnetlib.loginservice.properties.Properties;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.log4j.Logger;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.net.URISyntaxException;
+import java.util.Enumeration;
+
+public class Redirect {
+
+ private final static Logger logger = Logger.getLogger(Redirect.class);
+
+ private static String getDomain(String url) throws URISyntaxException {
+ URIBuilder uriBuilder = new URIBuilder(url);
+ return uriBuilder.getHost();
+ }
+
+ public static void setRedirect(HttpServletRequest request, Properties properties) {
+ HttpSession session = request.getSession();
+ Enumeration params = request.getParameterNames();
+ while (params.hasMoreElements()) {
+ String param = params.nextElement();
+ if(param.equalsIgnoreCase("redirect")) {
+ String redirect = request.getParameter(param);
+ try {
+ if(getDomain(redirect).endsWith(properties.getDomain())) {
+ session.setAttribute("redirect", redirect);
+ }
+ } catch (URISyntaxException e) {
+ logger.error(e.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/eu/dnetlib/loginservice/utils/ScopeReader.java b/src/main/java/eu/dnetlib/loginservice/utils/ScopeReader.java
new file mode 100644
index 0000000..096361e
--- /dev/null
+++ b/src/main/java/eu/dnetlib/loginservice/utils/ScopeReader.java
@@ -0,0 +1,25 @@
+package eu.dnetlib.loginservice.utils;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ScopeReader {
+
+ Set scopes;
+
+ public ScopeReader(String property) {
+ if (!property.trim().isEmpty()){
+ scopes = new HashSet<>();
+ Collections.addAll(scopes, property.split(","));
+ }
+ }
+
+ public Set getScopes() {
+ return scopes;
+ }
+
+ public void setScopes(Set scopes) {
+ this.scopes = scopes;
+ }
+}
diff --git a/src/main/java/eu/dnetlinb/loginservice/LoginServiceApplication.java b/src/main/java/eu/dnetlinb/loginservice/LoginServiceApplication.java
deleted file mode 100644
index 413447f..0000000
--- a/src/main/java/eu/dnetlinb/loginservice/LoginServiceApplication.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package eu.dnetlinb.loginservice;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class LoginServiceApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(LoginServiceApplication.class, args);
- }
-
-}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 8b13789..220bf44 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,9 @@
-
+authentication.domain=di.uoa.gr
+authentication.oidc.issuer=https://aai.openaire.eu/oidc/
+authentication.oidc.logout=https://aai.openaire.eu/proxy/saml2/idp/SingleLogoutService.php?ReturnTo=
+authentication.oidc.home=http://mpagasas.di.uoa.gr:8090/openid_connect_login
+authentication.oidc.scope=openid,profile,email,eduperson_entitlement
+authentication.oidc.id=id
+authentication.oidc.secret=secret
+authentication.session=openAIRESession
+authentication.redirect=http://mpagasas.di.uoa.gr:4600/reload
\ No newline at end of file
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
new file mode 100644
index 0000000..d9dc948
--- /dev/null
+++ b/src/main/resources/log4j.properties
@@ -0,0 +1,20 @@
+log4j.rootLogger = DEBUG, R
+
+log4j.logger.eu.dnetlib = DEBUG
+log4j.logger.org.springframework = DEBUG, S
+
+log4j.additivity.org.springframework = false
+
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=/var/log/dnet/login-service/login-service.log
+log4j.appender.R.MaxFileSize=10MB
+log4j.appender.R.MaxBackupIndex=10
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern= %d %p %t [%c] - %m%n
+
+log4j.appender.S=org.apache.log4j.RollingFileAppender
+log4j.appender.S.File=/var/log/dnet/login-service/login-service-spring.log
+log4j.appender.S.MaxFileSize=10MB
+log4j.appender.S.MaxBackupIndex=10
+log4j.appender.S.layout=org.apache.log4j.PatternLayout
+log4j.appender.S.layout.ConversionPattern= %d %p %t [%c] - %m%n
\ No newline at end of file
diff --git a/src/test/java/eu/dnetlinb/loginservice/LoginServiceApplicationTests.java b/src/test/java/eu/dnetlib/loginservice/LoginServiceApplicationTests.java
similarity index 84%
rename from src/test/java/eu/dnetlinb/loginservice/LoginServiceApplicationTests.java
rename to src/test/java/eu/dnetlib/loginservice/LoginServiceApplicationTests.java
index 9df54fc..f9ece22 100644
--- a/src/test/java/eu/dnetlinb/loginservice/LoginServiceApplicationTests.java
+++ b/src/test/java/eu/dnetlib/loginservice/LoginServiceApplicationTests.java
@@ -1,4 +1,4 @@
-package eu.dnetlinb.loginservice;
+package eu.dnetlib.loginservice;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;