Merge branch 'master' of gitlab.eudat.eu:dmp/OpenAIRE-EUDAT-DMP-service-pilot

This commit is contained in:
annampak 2017-09-28 18:07:49 +03:00
commit 266c5c0767
14 changed files with 536 additions and 14 deletions

View File

@ -7,10 +7,14 @@
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.http.version>1.19.0</project.http.version>
<project.oauth.version>1.19.0</project.oauth.version>
<dmp-backend-commons.version>0.0.1-SNAPSHOT</dmp-backend-commons.version>
<org.springframework.version>4.3.8.RELEASE</org.springframework.version>
<!-- <org.springframework.security.version>3.2.10.RELEASE</org.springframework.security.version> -->
<org.springframework.security.version>4.2.3.RELEASE</org.springframework.security.version>
<com.sun.jersey.version>1.19.1</com.sun.jersey.version>
<org.apache.tomcat.tomcat-jdbc.version>7.0.35</org.apache.tomcat.tomcat-jdbc.version>
<hibernate.version>5.2.9.Final</hibernate.version>
@ -203,6 +207,54 @@
<scope>runtime</scope>
</dependency>
<!-- Json Web Tokens -->
<!-- <dependency> -->
<!-- <groupId>io.jsonwebtoken</groupId> -->
<!-- <artifactId>jjwt</artifactId> -->
<!-- <version>0.7.0</version> -->
<!-- </dependency> -->
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-oauth2</artifactId>
<version>v2-rev75-1.19.0</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId>
<version>${project.http.version}</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>${project.oauth.version}</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${org.springframework.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${org.springframework.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Various libs -->
<dependency>
<groupId>org.apache.commons</groupId>
@ -211,8 +263,6 @@
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,12 @@
package dao.entities.security;
import java.util.UUID;
import dao.Dao;
import entities.security.UserInfo;
public interface UserInfoDao extends Dao<UserInfo, UUID> {
public UserInfo getByKey(String id, String email);
}

View File

@ -0,0 +1,37 @@
package dao.entities.security;
import java.util.List;
import java.util.UUID;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import dao.JpaDao;
import entities.security.UserInfo;
public class UserInfoDaoImpl extends JpaDao<UserInfo, UUID> implements UserInfoDao {
public UserInfo loadDetails(UserInfo t) {
// TODO Auto-generated method stub
return null;
}
@Override
public UserInfo getByKey(String id, String email) {
String queryString = "FROM UserInfo userInfo where userInfo.id = :userInfoID and userInfo.email = :userInfoEmail";
TypedQuery<UserInfo> typedQuery = entityManager.createQuery(queryString, UserInfo.class);
typedQuery.setParameter("userInfoID", id);
typedQuery.setParameter("userInfoEmail", email);
try {
return typedQuery.getSingleResult();
}
catch(NoResultException ex) {
return null;
}
}
}

View File

@ -0,0 +1,151 @@
package entities.security;
import java.io.Serializable;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@Entity
@Table(name="\"UserInfo\"")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="autoid")
public class UserInfo implements Serializable{
private static final long serialVersionUID = 1225151430484658395L;
@Id
@GeneratedValue
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Column(name = "autoid", updatable = false, nullable = false, columnDefinition = "BINARY(16)")
private UUID autoid;
//required
@Column(name = "id")
String id = null;
@Column(name = "email")
String email = null;
//non required
@Column(name = "\"emailIsVerified\"", nullable = true)
Boolean emailIsVerified = null;
@Column(name = "name", nullable = true)
String name = null;
@Column(name = "\"pictureUrl\"", nullable = true)
String pictureUrl = null;
@Column(name = "locale", nullable = true)
String locale = null;
@Column(name = "\"familyName\"", nullable = true)
String familyName = null;
@Column(name = "\"givenName\"", nullable = true)
String givenName = null;
@Type(type="typedefinition.XMLType")
@Column(name = "additionalinfo", columnDefinition = "xml", nullable = true)
private String additionalinfo;
public UserInfo () {}
public UserInfo(String id, String email, Boolean emailIsVerified, String name, String pictureUrl, String locale, String familyName, String givenName, String additionalinfo) {
this.id = id;
this.email = email;
this.emailIsVerified = emailIsVerified;
this.name = name;
this.pictureUrl = pictureUrl;
this.locale = locale;
this.familyName = familyName;
this.givenName = givenName;
this.additionalinfo = additionalinfo;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isEmailIsVerified() {
return emailIsVerified;
}
public void setEmailIsVerified(boolean emailIsVerified) {
this.emailIsVerified = emailIsVerified;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPictureUrl() {
return pictureUrl;
}
public void setPictureUrl(String pictureUrl) {
this.pictureUrl = pictureUrl;
}
public String getLocale() {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
public String getFamilyName() {
return familyName;
}
public void setFamilyName(String familyName) {
this.familyName = familyName;
}
public String getGivenName() {
return givenName;
}
public void setGivenName(String givenName) {
this.givenName = givenName;
}
public Boolean getEmailIsVerified() {
return emailIsVerified;
}
public void setEmailIsVerified(Boolean emailIsVerified) {
this.emailIsVerified = emailIsVerified;
}
public String getAdditionalinfo() {
return additionalinfo;
}
public void setAdditionalinfo(String additionalinfo) {
this.additionalinfo = additionalinfo;
}
@Override
public String toString() {
return "UserInfo [id=" + id + ", email=" + email + ", emailIsVerified=" + emailIsVerified
+ ", name=" + name + ", pictureUrl=" + pictureUrl + ", locale=" + locale + ", familyName=" + familyName
+ ", givenName=" + givenName + ", additionalinfo=" + additionalinfo + "]";
}
}

View File

@ -0,0 +1,11 @@
package exceptions;
public class NonValidTokenException extends Exception {
private static final long serialVersionUID = -2834659827755141154L;
public NonValidTokenException(String msg) {
super(msg);
}
}

View File

@ -76,6 +76,7 @@ public class BackendInterface {
// FETCH BY DMP(S)
@RequestMapping(method = RequestMethod.GET, value = { "/DMP" }, produces="text/plain")

View File

@ -0,0 +1,60 @@
package security;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import dao.entities.security.UserInfoDao;
import entities.security.UserInfo;
import exceptions.NonValidTokenException;
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired private UserInfoDao userInfoDao;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (authentication != null) {
// check whether the token is valid
String token = (String)authentication.getCredentials();
GoogleTokenValidator gValidator = new GoogleTokenValidator();
UserInfo userInfo = null;
try {
userInfo = gValidator.validateToken(token);
} catch (NonValidTokenException e) {
System.out.println("Could not validate a user by his token! Reason: "+e.getMessage());
throw new AuthenticationServiceException("Token validation failed - Not a valid token");
}
//store to database if new
UserInfo existingUserInfo = userInfoDao.getByKey(userInfo.getId(), userInfo.getEmail());
if(existingUserInfo == null)
userInfoDao.create(userInfo);
// if reached this point, authentication is ok
return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), new ArrayList<>());
}
else
throw new AuthenticationServiceException("Authentication failed");
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}

View File

@ -0,0 +1,74 @@
package security;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import entities.security.UserInfo;
import exceptions.NonValidTokenException;
public class GoogleTokenValidator {
private static final JacksonFactory jacksonFactory = new JacksonFactory();
private static final HttpTransport transport = new NetHttpTransport();
private static final List<String> clientIDs = Arrays.asList("1010962018903-glegmqudqtl1lub0150vacopbu06lgsg.apps.googleusercontent.com");
private GoogleIdTokenVerifier verifier = null;
public GoogleTokenValidator() {
verifier = new GoogleIdTokenVerifier.Builder(transport, jacksonFactory)
.setAudience(clientIDs)
// Or, if multiple clients access the backend:
//.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
.build();
}
public UserInfo validateToken(String token) throws NonValidTokenException {
GoogleIdToken idToken = null;
try {
idToken = verifier.verify(token);
}
catch(GeneralSecurityException ex) {
throw new NonValidTokenException("Token is not valid -> "+ex.getMessage());
}
catch(IOException ex) {
throw new NonValidTokenException("Could not verify token -> "+ex.getMessage());
}
catch(IllegalArgumentException ex) {
throw new NonValidTokenException("Could not verify token");
}
if (idToken != null) {
Payload payload = idToken.getPayload();
UserInfo userInfo = new UserInfo(payload.getSubject(), payload.getEmail(),
payload.getEmailVerified(), (String)payload.get("name"), (String)payload.get("picture"),
(String)payload.get("locale"), (String)payload.get("family_name"), (String)payload.get("given_name"), "");
// System.out.println(userInfo.toString());
return userInfo;
} else {
throw new NonValidTokenException("Not a valid token");
}
}
}

View File

@ -0,0 +1,35 @@
package security;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;
public class TokenAuthenticationFilter extends GenericFilterBean {
private static final String HEADER_TOKEN_FIELD = "oauth2-token";
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
String accessToken = httpRequest.getHeader(HEADER_TOKEN_FIELD);
if(accessToken==null) accessToken = "";
//just pass the token into the credentials object of the UsernamePasswordAuthenticationToken class
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("google-user", accessToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
}

View File

@ -29,7 +29,15 @@
<bean id="springApplicationContext" class="dao.SpringJpaDaoFactory" />
<bean id="databaseColumnType" class="typedefinition.PostgreSQLDatabaseColumnType" />
<!-- <bean id="securityConfig" class="security.SecurityConfig" /> -->
<!-- <bean id="securityWebApplicationInitializer" class="security.SecurityWebApplicationInitializer" /> -->
<bean id="tokenAuthenticationFilter" class="security.TokenAuthenticationFilter" />
<bean id="customAuthenticationProvider" class="security.CustomAuthenticationProvider" />
<bean id="emf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="DMPBackendPersistence" />
<property name="jpaProperties">
@ -87,6 +95,7 @@
<bean id="registryDao" class="dao.entities.RegistryDaoImpl" />
<bean id="researcherDao" class="dao.entities.ResearcherDaoImpl" />
<bean id="serviceDao" class="dao.entities.ServiceDaoImpl" />
<bean id="userInfoDao" class="dao.entities.security.UserInfoDaoImpl" />
<context:annotation-config />

View File

@ -5,9 +5,9 @@
##########################Persistence##########################################
persistence.jdbc.driver = org.postgresql.Driver
persistence.jdbc.url = jdbc:postgresql://localhost:5432/db
persistence.dbusername = db-user
persistence.dbpassword = db-pass
persistence.jdbc.url = jdbc:postgresql://develdb1.madgik.di.uoa.gr:5432/dmptool
persistence.dbusername = dmptool
persistence.dbpassword = dmpt00lu$r
##########################/Persistence##########################################
@ -42,5 +42,4 @@ persistence.hibernate.connectionpool.c3p0.idle_connection_test_period = 3600
persistence.hibernate.connectionpool.c3p0.test_connection_on_checkin = true
persistence.hibernate.connectionpool.c3p0.test_connection_on_checkout = false
persistence.hibernate.connectionpool.c3p0.preferred_test_query = select 1
########################Persistence/Hibernate/Connection pool####################
########################Persistence/Hibernate/Connection pool####################

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<!--
-->
<context:component-scan base-package="security.*" />
<!--
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
-->
<http use-expressions="true" create-session="stateless" auto-config='true'>
<custom-filter after="BASIC_AUTH_FILTER" ref="tokenAuthenticationFilter" />
<!-- is authenticated means that they can see even if no correct creds provided -->
<!-- <intercept-url pattern="/customers/**" access="isAuthenticated()" /> -->
<intercept-url pattern="/**" access="isAuthenticated()" />
<http-basic/>
</http>
<authentication-manager>
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
<!--
<authentication-manager>
<authentication-provider>
<user-service>
<user name="mkyong" password="123456" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
-->
<beans:bean id="tokenFilter" class="security.TokenAuthenticationFilter"/>
</beans:beans>

View File

@ -31,11 +31,24 @@
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
<param-value>/WEB-INF/applicationContext.xml,/WEB-INF/spring-security.xml
</param-value>
</context-param>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!-- THIS FILTER IS FOR SPRING SECURITY -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

View File

@ -1,4 +1,3 @@
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
@ -26,6 +25,7 @@ drop table if exists "Registry" cascade;
drop table if exists "DatasetService" cascade;
drop table if exists "DatasetRegistry" cascade;
drop table if exists "DatasetDataRepository" cascade;
drop table if exists "UserInfo" cascade;
-- CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
@ -420,12 +420,12 @@ CREATE TABLE "DatasetDataRepository" (
"ID" uuid DEFAULT uuid_generate_v4() NOT NULL
);
ALTER TABLE "DatasetDataRepository" OWNER TO dmptool;
COMMENT ON TABLE "DatasetDataRepository" IS 'Linking Dataset to DataRepository';
ALTER TABLE ONLY "DatasetDataRepository"
ADD CONSTRAINT "DatasetDataRepositoryDatasetReference" FOREIGN KEY ("Dataset") REFERENCES "Dataset"("ID");
@ -447,6 +447,21 @@ ALTER TABLE ONLY "DatasetService"
ADD CONSTRAINT "DatasetServiceServiceReference" FOREIGN KEY ("Service") REFERENCES "Service"("ID");
CREATE TABLE "UserInfo" (
"autoid" uuid DEFAULT uuid_generate_v4() NOT NULL,
"id" character varying(500),
"email" character varying(250),
"emailIsVerified" boolean,
"name" character varying(250),
"pictureUrl" character varying(500),
"locale" character varying(50),
"familyName" character varying(250),
"givenName" character varying(250),
"additionalinfo" xml,
PRIMARY KEY (id, email)
);
REVOKE ALL ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM postgres;
GRANT ALL ON SCHEMA public TO postgres;