Move all components from login-service to login-core
This commit is contained in:
commit
63d9be79c9
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>eu.dnetlib</groupId>
|
||||||
|
<artifactId>uoa-spring-boot-parent</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>uoa-login-core</artifactId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>uoa-login-core</name>
|
||||||
|
<scm>
|
||||||
|
<developerConnection>scm:git:gitea@code-repo.d4science.org:MaDgIK/uoa-login-core.git</developerConnection>
|
||||||
|
<tag>HEAD</tag>
|
||||||
|
</scm>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<timestampLogincORE>${maven.build.timestamp}</timestampLogincORE>
|
||||||
|
<maven.build.timestamp.format>E MMM dd HH:mm:ss z yyyy</maven.build.timestamp.format>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- Redis -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.session</groupId>
|
||||||
|
<artifactId>spring-session-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>biz.paluch.redis</groupId>
|
||||||
|
<artifactId>lettuce</artifactId>
|
||||||
|
<version>4.3.3.Final</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Mitre -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mitre</groupId>
|
||||||
|
<artifactId>openid-connect-client</artifactId>
|
||||||
|
<version>1.3.0</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<finalName>uoa-login-core</finalName>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,38 @@
|
||||||
|
package eu.dnetlib.authentication.configuration;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
@ConfigurationProperties("api")
|
||||||
|
public class APIProperties {
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private String description;
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
public APIProperties() {
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package eu.dnetlib.authentication.configuration;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties({Properties.class, APIProperties.class})
|
||||||
|
@ComponentScan(basePackages = {"eu.dnetlib.authentication"})
|
||||||
|
public class AuthenticationConfiguration {
|
||||||
|
|
||||||
|
public AuthenticationConfiguration() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package eu.dnetlib.authentication.configuration;
|
||||||
|
|
||||||
|
public class OIDC {
|
||||||
|
|
||||||
|
private String issuer;
|
||||||
|
private String home;
|
||||||
|
private String redirect;
|
||||||
|
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 getRedirect() {
|
||||||
|
return redirect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirect(String redirect) {
|
||||||
|
this.redirect = redirect;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package eu.dnetlib.authentication.configuration;
|
||||||
|
|
||||||
|
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 accessToken;
|
||||||
|
private String redirect;
|
||||||
|
private String authoritiesMapper;
|
||||||
|
private Boolean keycloak;
|
||||||
|
|
||||||
|
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 getAccessToken() {
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessToken(String accessToken) {
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRedirect() {
|
||||||
|
return redirect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirect(String redirect) {
|
||||||
|
this.redirect = redirect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthoritiesMapper() {
|
||||||
|
return authoritiesMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthoritiesMapper(String authoritiesMapper) {
|
||||||
|
this.authoritiesMapper = authoritiesMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getKeycloak() {
|
||||||
|
return keycloak;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeycloak(Boolean keycloak) {
|
||||||
|
this.keycloak = keycloak;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package eu.dnetlib.authentication.configuration;
|
||||||
|
|
||||||
|
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 + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package eu.dnetlib.authentication.controllers;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
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.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HealthController {
|
||||||
|
private final Logger log = LogManager.getLogger(this.getClass());
|
||||||
|
private final Properties properties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public HealthController(Properties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = {"", "/health_check"}, method = RequestMethod.GET)
|
||||||
|
public String hello() {
|
||||||
|
log.debug("Hello from Login service!");
|
||||||
|
return "Hello from Login service!";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAnyAuthority('PORTAL_ADMINISTRATOR')")
|
||||||
|
@RequestMapping(value = "/health_check/advanced", method = RequestMethod.GET)
|
||||||
|
public Map<String, String> checkEverything() {
|
||||||
|
Map<String, String> response = new HashMap<>();
|
||||||
|
response.put("authentication.domain", properties.getDomain());
|
||||||
|
response.put("authentication.keycloak", properties.getKeycloak().toString());
|
||||||
|
response.put("authentication.redis.host", properties.getRedis().getHost());
|
||||||
|
response.put("authentication.oidc.issuer", properties.getOidc().getIssuer());
|
||||||
|
response.put("authentication.oidc.logout", properties.getOidc().getLogout());
|
||||||
|
response.put("authentication.oidc.home", properties.getOidc().getHome());
|
||||||
|
response.put("authentication.oidc.redirect", properties.getOidc().getRedirect());
|
||||||
|
response.put("authentication.oidc.scope", properties.getOidc().getScope());
|
||||||
|
response.put("authentication.oidc.id", properties.getOidc().getId());
|
||||||
|
response.put("authentication.oidc.secret", properties.getOidc().getSecret());
|
||||||
|
response.put("authentication.session", properties.getSession());
|
||||||
|
response.put("authentication.accessToken", properties.getAccessToken());
|
||||||
|
response.put("authentication.redirect", properties.getRedirect());
|
||||||
|
response.put("authentication.authorities-mapper", properties.getAuthoritiesMapper());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package eu.dnetlib.authentication.controllers;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.entities.User;
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import eu.dnetlib.authentication.services.UserInfoService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
private final UserInfoService userInfoService;
|
||||||
|
private final Properties properties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public UserController(UserInfoService userInfoService, Properties properties) {
|
||||||
|
this.userInfoService = userInfoService;
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/userInfo", method = RequestMethod.GET)
|
||||||
|
public ResponseEntity<User> getUserInfo() {
|
||||||
|
return ResponseEntity.ok(userInfoService.getUserInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/redirect",method = RequestMethod.GET)
|
||||||
|
public void redirect(HttpServletRequest request, HttpServletResponse response) 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(redirect);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package eu.dnetlib.authentication.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<String> 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<String> getRoles() {
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoles(Set<String> roles) {
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package eu.dnetlib.authentication.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package eu.dnetlib.authentication.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package eu.dnetlib.authentication.security;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
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 Properties properties;
|
||||||
|
|
||||||
|
private static final Logger logger = LogManager.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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package eu.dnetlib.authentication.security;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import eu.dnetlib.authentication.security.oidc.OpenAIREAuthenticationFilter;
|
||||||
|
import eu.dnetlib.authentication.security.oidc.OpenAIREAuthenticationSuccessHandler;
|
||||||
|
import eu.dnetlib.authentication.security.oidc.OpenAIRELogoutHandler;
|
||||||
|
import eu.dnetlib.authentication.security.oidc.OpenAIRELogoutSuccessHandler;
|
||||||
|
import eu.dnetlib.authentication.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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package eu.dnetlib.authentication.security.initiliazers;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import eu.dnetlib.authentication.security.oidc.OpenAIREAuthoritiesMapper;
|
||||||
|
import eu.dnetlib.authentication.security.oidc.OpenAIREUserInfoFetcher;
|
||||||
|
import eu.dnetlib.authentication.utils.PropertyReader;
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
|
import org.mitre.oauth2.model.RegisteredClient;
|
||||||
|
import org.mitre.openid.connect.client.OIDCAuthenticationProvider;
|
||||||
|
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.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class Configurations {
|
||||||
|
|
||||||
|
private final Properties properties;
|
||||||
|
private final PropertyReader scopeReader;
|
||||||
|
private final OpenAIREAuthoritiesMapper authoritiesMapper;
|
||||||
|
private final OpenAIREUserInfoFetcher userInfoFetcher;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public Configurations(Properties properties, OpenAIREAuthoritiesMapper authoritiesMapper, OpenAIREUserInfoFetcher userInfoFetcher, PropertyReader scopeReader) {
|
||||||
|
this.properties = properties;
|
||||||
|
this.authoritiesMapper = authoritiesMapper;
|
||||||
|
this.userInfoFetcher = userInfoFetcher;
|
||||||
|
this.scopeReader = scopeReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public OIDCAuthenticationProvider provider() {
|
||||||
|
OIDCAuthenticationProvider provider = new OIDCAuthenticationProvider();
|
||||||
|
if(properties.getKeycloak()) {
|
||||||
|
provider.setUserInfoFetcher(this.userInfoFetcher);
|
||||||
|
}
|
||||||
|
if(this.properties.getAuthoritiesMapper() != null && this.scopeReader.getScopes().contains(this.properties.getAuthoritiesMapper())) {
|
||||||
|
provider.setAuthoritiesMapper(this.authoritiesMapper);
|
||||||
|
}
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ServerConfiguration serverConfiguration() {
|
||||||
|
String issuer = properties.getOidc().getIssuer();
|
||||||
|
ServerConfiguration serverConfiguration = new ServerConfiguration();
|
||||||
|
serverConfiguration.setIssuer(issuer);
|
||||||
|
Boolean keycloak = properties.getKeycloak();
|
||||||
|
if(keycloak) {
|
||||||
|
serverConfiguration.setAuthorizationEndpointUri(issuer + "/protocol/openid-connect/auth");
|
||||||
|
serverConfiguration.setTokenEndpointUri(issuer + "/protocol/openid-connect/token");
|
||||||
|
serverConfiguration.setUserInfoUri(issuer + "/protocol/openid-connect/userinfo");
|
||||||
|
serverConfiguration.setJwksUri(issuer + "/protocol/openid-connect/certs");
|
||||||
|
} else {
|
||||||
|
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(new HashSet<>(Arrays.asList(properties.getOidc().getHome(), properties.getOidc().getRedirect())));
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package eu.dnetlib.authentication.security.initiliazers;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import eu.dnetlib.authentication.utils.EntryPoint;
|
||||||
|
import eu.dnetlib.authentication.utils.PropertyReader;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class Primitives {
|
||||||
|
|
||||||
|
private final Properties properties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public Primitives(Properties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PropertyReader scopeReader() {
|
||||||
|
return new PropertyReader(this.properties.getOidc().getScope());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DefaultWebSecurityExpressionHandler handler() {
|
||||||
|
return new DefaultWebSecurityExpressionHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PlainAuthRequestUrlBuilder builder() {
|
||||||
|
return new PlainAuthRequestUrlBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package eu.dnetlib.authentication.security.initiliazers;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
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<String, ServerConfiguration> servers = new HashMap<>();
|
||||||
|
servers.put(properties.getOidc().getIssuer(), serverConfiguration);
|
||||||
|
configurationService.setServers(servers);
|
||||||
|
return configurationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public StaticClientConfigurationService clientConfigurationService() {
|
||||||
|
StaticClientConfigurationService configurationService = new StaticClientConfigurationService();
|
||||||
|
Map<String, RegisteredClient> clients = new HashMap<>();
|
||||||
|
clients.put(properties.getOidc().getIssuer(), clientConfiguration);
|
||||||
|
configurationService.setClients(clients);
|
||||||
|
return configurationService;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package eu.dnetlib.authentication.security.oidc;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import eu.dnetlib.authentication.utils.Redirect;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.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 = LogManager.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package eu.dnetlib.authentication.security.oidc;
|
||||||
|
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.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 = LogManager.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(properties.getAccessToken(), 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package eu.dnetlib.authentication.security.oidc;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.nimbusds.jwt.JWT;
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import eu.dnetlib.authentication.utils.AuthoritiesMapper;
|
||||||
|
import org.mitre.openid.connect.client.OIDCAuthoritiesMapper;
|
||||||
|
import org.mitre.openid.connect.model.UserInfo;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class OpenAIREAuthoritiesMapper implements OIDCAuthoritiesMapper {
|
||||||
|
|
||||||
|
private final Properties properties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
OpenAIREAuthoritiesMapper(Properties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> mapAuthorities(JWT jwtToken, UserInfo userInfo) {
|
||||||
|
JsonArray entitlements = userInfo.getSource().getAsJsonArray(properties.getAuthoritiesMapper());
|
||||||
|
return AuthoritiesMapper.map(entitlements);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package eu.dnetlib.authentication.security.oidc;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import eu.dnetlib.authentication.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 final Properties properties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public OpenAIRELogoutHandler(Properties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
||||||
|
Redirect.setRedirect(request, properties);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package eu.dnetlib.authentication.security.oidc;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.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.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class OpenAIRELogoutSuccessHandler implements LogoutSuccessHandler {
|
||||||
|
|
||||||
|
private final Properties properties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public OpenAIRELogoutSuccessHandler(Properties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String encodeValue(String value) throws UnsupportedEncodingException {
|
||||||
|
return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
|
||||||
|
if(properties.getOidc().getRedirect() == null) {
|
||||||
|
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() + encodeValue(redirect));
|
||||||
|
} else {
|
||||||
|
StringBuilder sb = new StringBuilder(properties.getOidc().getIssuer());
|
||||||
|
if(properties.getKeycloak()) {
|
||||||
|
sb.append("/protocol/openid-connect/logout");
|
||||||
|
sb.append("?client_id=").append(properties.getOidc().getId());
|
||||||
|
sb.append("&post_logout_redirect_uri=").append(encodeValue(properties.getOidc().getRedirect()));
|
||||||
|
} else {
|
||||||
|
sb.append("/saml/logout");
|
||||||
|
}
|
||||||
|
response.sendRedirect(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package eu.dnetlib.authentication.security.oidc;
|
||||||
|
|
||||||
|
import org.mitre.openid.connect.client.UserInfoFetcher;
|
||||||
|
import org.mitre.openid.connect.model.PendingOIDCAuthenticationToken;
|
||||||
|
import org.mitre.openid.connect.model.UserInfo;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class OpenAIREUserInfoFetcher extends UserInfoFetcher {
|
||||||
|
|
||||||
|
public OpenAIREUserInfoFetcher() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserInfo loadUserInfo(PendingOIDCAuthenticationToken token) {
|
||||||
|
UserInfo userInfo = super.loadUserInfo(token);
|
||||||
|
userInfo.setGivenName(encoder(userInfo.getGivenName()));
|
||||||
|
userInfo.setFamilyName(encoder(userInfo.getFamilyName()));
|
||||||
|
userInfo.setName(encoder(userInfo.getName()));
|
||||||
|
return userInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String encoder(String value) {
|
||||||
|
String decodedString = new String(value.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return new String(decodedString.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package eu.dnetlib.authentication.services;
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.entities.User;
|
||||||
|
import eu.dnetlib.authentication.exception.ResourceNotFoundException;
|
||||||
|
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserInfoService {
|
||||||
|
|
||||||
|
public User getUserInfo() throws ResourceNotFoundException {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
if(authentication instanceof OIDCAuthenticationToken) {
|
||||||
|
return new User((OIDCAuthenticationToken) authentication);
|
||||||
|
}
|
||||||
|
throw new ResourceNotFoundException("No Session has been found");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package eu.dnetlib.authentication.utils;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.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 = LogManager.getLogger(AuthoritiesMapper.class);
|
||||||
|
|
||||||
|
public static Collection<? extends GrantedAuthority> map(JsonArray entitlements) {
|
||||||
|
HashSet<SimpleGrantedAuthority> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package eu.dnetlib.authentication.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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package eu.dnetlib.authentication.utils;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class PropertyReader {
|
||||||
|
|
||||||
|
Set<String> scopes;
|
||||||
|
|
||||||
|
public PropertyReader(String property) {
|
||||||
|
if (!property.trim().isEmpty()){
|
||||||
|
scopes = new HashSet<>();
|
||||||
|
Collections.addAll(scopes, property.split(","));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getScopes() {
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScopes(Set<String> scopes) {
|
||||||
|
this.scopes = scopes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package eu.dnetlib.authentication.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import eu.dnetlib.authentication.configuration.Properties;
|
||||||
|
import org.apache.http.client.utils.URIBuilder;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.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 = LogManager.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<String> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
authentication.domain=di.uoa.gr
|
||||||
|
|
||||||
|
authentication.keycloak=false
|
||||||
|
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:19080/login-service/openid_connect_login
|
||||||
|
authentication.oidc.scope=openid,profile,email,eduperson_entitlement
|
||||||
|
authentication.oidc.id=id
|
||||||
|
authentication.oidc.secret=secret
|
||||||
|
#authentication.oidc.redirect=http://mpagasas.di.uoa.gr:19080/login-service/redirect
|
||||||
|
|
||||||
|
authentication.session=openAIRESession
|
||||||
|
authentication.accessToken=AccessToken
|
||||||
|
authentication.redirect=http://mpagasas.di.uoa.gr:4600/reload
|
||||||
|
|
||||||
|
#authentication.authorities-mapper=eduperson_entitlement
|
Loading…
Reference in New Issue