diff --git a/dmp-backend/src/main/java/dao/entities/security/UserInfoDao.java b/dmp-backend/src/main/java/dao/entities/security/UserInfoDao.java new file mode 100644 index 000000000..0922b1fbc --- /dev/null +++ b/dmp-backend/src/main/java/dao/entities/security/UserInfoDao.java @@ -0,0 +1,12 @@ +package dao.entities.security; + +import java.util.UUID; + +import dao.Dao; +import entities.security.UserInfo; + +public interface UserInfoDao extends Dao { + + public UserInfo getByKey(String id, String email); + +} \ No newline at end of file diff --git a/dmp-backend/src/main/java/dao/entities/security/UserInfoDaoImpl.java b/dmp-backend/src/main/java/dao/entities/security/UserInfoDaoImpl.java new file mode 100644 index 000000000..3f257d8f5 --- /dev/null +++ b/dmp-backend/src/main/java/dao/entities/security/UserInfoDaoImpl.java @@ -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 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 typedQuery = entityManager.createQuery(queryString, UserInfo.class); + typedQuery.setParameter("userInfoID", id); + typedQuery.setParameter("userInfoEmail", email); + try { + return typedQuery.getSingleResult(); + } + catch(NoResultException ex) { + return null; + } + } + + +} \ No newline at end of file diff --git a/dmp-backend/src/main/java/entities/security/UserInfo.java b/dmp-backend/src/main/java/entities/security/UserInfo.java new file mode 100644 index 000000000..1e95a0c21 --- /dev/null +++ b/dmp-backend/src/main/java/entities/security/UserInfo.java @@ -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 + "]"; + } + + + + +} diff --git a/dmp-backend/src/main/java/rest/TokenManager.java b/dmp-backend/src/main/java/rest/TokenManager.java deleted file mode 100644 index d302de706..000000000 --- a/dmp-backend/src/main/java/rest/TokenManager.java +++ /dev/null @@ -1,157 +0,0 @@ -//package rest; -// -//import java.io.BufferedReader; -//import java.io.IOException; -//import java.io.InputStreamReader; -//import java.io.Serializable; -//import java.io.UnsupportedEncodingException; -//import java.net.HttpURLConnection; -//import java.net.URL; -//import java.security.GeneralSecurityException; -//import java.util.Arrays; -//import java.util.Base64; -//import java.util.Collections; -//import java.util.List; -//import java.util.UUID; -// -//import org.springframework.http.HttpStatus; -//import org.springframework.http.ResponseEntity; -//import org.springframework.web.bind.annotation.CrossOrigin; -//import org.springframework.web.bind.annotation.RequestBody; -//import org.springframework.web.bind.annotation.RequestMapping; -//import org.springframework.web.bind.annotation.RequestMethod; -//import org.springframework.web.bind.annotation.RequestParam; -//import org.springframework.web.bind.annotation.ResponseBody; -//import org.springframework.web.bind.annotation.RestController; -// -//import com.fasterxml.jackson.databind.ObjectMapper; -// -//import entities.DMP; -////import io.jsonwebtoken.Claims; -////import io.jsonwebtoken.ExpiredJwtException; -////import io.jsonwebtoken.Jws; -////import io.jsonwebtoken.Jwts; -////import io.jsonwebtoken.MalformedJwtException; -////import io.jsonwebtoken.SignatureException; -////import io.jsonwebtoken.UnsupportedJwtException; -////import security.GoogleKey; -////import security.GoogleKeys; -// -// -//import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; -//import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; -//import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; -//import com.google.api.client.http.HttpTransport; -//import com.google.api.client.http.apache.ApacheHttpTransport; -//import com.google.api.client.http.javanet.NetHttpTransport; -//import com.google.api.client.json.JsonFactory; -//import com.google.api.client.json.jackson2.JacksonFactory; -// -// -// -//@RestController -//@CrossOrigin -//public class TokenManager { -// -// -//// public static final String GOOGLE_KEYS_URL = "https://www.googleapis.com/oauth2/v3/certs"; -//// public static GoogleKeys GOOGLE_KEYS; -// -// private static final JacksonFactory jacksonFactory = new JacksonFactory(); -// private static final HttpTransport transport = new NetHttpTransport(); -// -// private static GoogleIdTokenVerifier verifier; -// -// private static final List clientIDs = Arrays.asList("1010962018903-glegmqudqtl1lub0150vacopbu06lgsg.apps.googleusercontent.com"); -// -// -// -// -// -// -// static { -// 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(); -// } -// -// -// -// -// @RequestMapping(method = RequestMethod.POST, value = { "/login" }, produces="text/plain") -// public @ResponseBody ResponseEntity login( -// @RequestParam("token") String token -// ){ -// -// System.out.println(token); -// -// // 1. CHECK IF IT'S A VALID TOKEN -// -// GoogleIdToken idToken = null; -// try { -// idToken = verifier.verify(token); -// } -// catch(GeneralSecurityException ex) { -// return ResponseEntity.status(HttpStatus.FORBIDDEN).body("{'reason': 'Token is not valid'}"); -// } -// catch(IOException ex) { -// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("{'reason': 'Could not verify token'}"); -// } -// -// -// if (idToken != null) { -// Payload payload = idToken.getPayload(); -// -// System.out.println("============================="); -// // Print user identifier -// String userId = payload.getSubject(); -// System.out.println("User ID: " + userId); -// -// // Get profile information from payload -// String email = payload.getEmail(); -// boolean emailVerified = Boolean.valueOf(payload.getEmailVerified()); -// String name = (String) payload.get("name"); -// String pictureUrl = (String) payload.get("picture"); -// String locale = (String) payload.get("locale"); -// String familyName = (String) payload.get("family_name"); -// String givenName = (String) payload.get("given_name"); -// -// System.out.println(email); -// System.out.println(name); -// System.out.println(familyName); -// System.out.println(locale); -// System.out.println(givenName); -// System.out.println(emailVerified); -// System.out.println(pictureUrl); -// -// -// } else { -// System.out.println("Invalid ID token."); -// } -// -// -// // 2.1 IF SO, ADD USER ON THE DATABASE -// -// // 2.2 also handle it within the session (create a c\\.ustom session) -// -// -// -// return ResponseEntity.status(HttpStatus.OK).body("{'status': 'ok'}"); -// -//// try { -//// List allIDs = dMPDao.listAllIDs(); -//// return ResponseEntity.status(HttpStatus.OK).body(new ObjectMapper().writeValueAsString(allIDs)); -//// } -//// catch(Exception ex) { -//// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Serialization issue: "+ex.getMessage()); -//// } -// -// -// } -// -// -// -//} -// diff --git a/dmp-backend/src/main/java/security/CustomAuthenticationProvider.java b/dmp-backend/src/main/java/security/CustomAuthenticationProvider.java index 9a68d7ed7..f787b4787 100644 --- a/dmp-backend/src/main/java/security/CustomAuthenticationProvider.java +++ b/dmp-backend/src/main/java/security/CustomAuthenticationProvider.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import javax.servlet.http.HttpServletRequest; +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; @@ -16,18 +17,39 @@ import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +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 { - System.out.println("Running authentication provider's authenticate()"); - if(authentication == null) { - throw new AuthenticationServiceException("Authentication failed"); + 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); } + else + throw new AuthenticationServiceException("Authentication failed"); //authentication is ok return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), new ArrayList<>()); diff --git a/dmp-backend/src/main/java/security/GoogleTokenValidator.java b/dmp-backend/src/main/java/security/GoogleTokenValidator.java index 9d4c5b204..d9651989a 100644 --- a/dmp-backend/src/main/java/security/GoogleTokenValidator.java +++ b/dmp-backend/src/main/java/security/GoogleTokenValidator.java @@ -15,8 +15,8 @@ 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; -import security.entities.UserInfo; public class GoogleTokenValidator { @@ -59,9 +59,9 @@ public class GoogleTokenValidator { 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")); + (String)payload.get("locale"), (String)payload.get("family_name"), (String)payload.get("given_name"), ""); - System.out.println(userInfo.toString()); +// System.out.println(userInfo.toString()); return userInfo; diff --git a/dmp-backend/src/main/java/security/SecurityConfig.java b/dmp-backend/src/main/java/security/SecurityConfig.java deleted file mode 100644 index 65489b787..000000000 --- a/dmp-backend/src/main/java/security/SecurityConfig.java +++ /dev/null @@ -1,42 +0,0 @@ -//package security; -// -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.context.annotation.ComponentScan; -//import org.springframework.context.annotation.Configuration; -//import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -//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; -// -////@Configuration -//@EnableWebSecurity -//public class SecurityConfig extends WebSecurityConfigurerAdapter { -// -// @Autowired -// private CustomAuthenticationProvider authProvider; -// -// @Override -// protected void configure(AuthenticationManagerBuilder auth) throws Exception { -// System.out.println("inside SecurityConfig.configure(auth) "); -// -// auth.authenticationProvider(authProvider); -// } -// -// @Override -// protected void configure(HttpSecurity http) throws Exception { -// -// System.out.println("inside SecurityConfig.configure(http) "); -// -// http -// .authorizeRequests() -// .anyRequest() -// .authenticated() -// .and() -// .httpBasic(); -// -// http.addFilterBefore(new TokenAuthenticationFilter(), BasicAuthenticationFilter.class); -// -// } -// -//} diff --git a/dmp-backend/src/main/java/security/TokenAuthenticationFilter.java b/dmp-backend/src/main/java/security/TokenAuthenticationFilter.java index 3634f7cf5..d4a4cf5f0 100644 --- a/dmp-backend/src/main/java/security/TokenAuthenticationFilter.java +++ b/dmp-backend/src/main/java/security/TokenAuthenticationFilter.java @@ -12,35 +12,24 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.GenericFilterBean; +import entities.security.UserInfo; import exceptions.NonValidTokenException; -import security.entities.UserInfo; 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; - System.out.println("in TokenAuthenticationFilter.doFilter"); + final String accessToken = httpRequest.getHeader(HEADER_TOKEN_FIELD); + //just pass the token into the credentials object of the UsernamePasswordAuthenticationToken class + final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("google-user", accessToken); + SecurityContextHolder.getContext().setAuthentication(authentication); - // extract token from header - final String accessToken = httpRequest.getHeader("oauth2-token"); - if (accessToken != null) { - // get and check whether token is valid ( from DB or file wherever you are storing the token) - - GoogleTokenValidator gValidator = new GoogleTokenValidator(); - UserInfo userInfo = null; - - try { - userInfo = gValidator.validateToken(accessToken); - final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userInfo.getEmail(), accessToken); - SecurityContextHolder.getContext().setAuthentication(authentication); - } catch (NonValidTokenException e) { - System.out.println("Could not validate a user by his token! Reason: "+e.getMessage()); - } - } - chain.doFilter(request, response); } diff --git a/dmp-backend/src/main/java/security/entities/UserInfo.java b/dmp-backend/src/main/java/security/entities/UserInfo.java deleted file mode 100644 index 9cb3a19e5..000000000 --- a/dmp-backend/src/main/java/security/entities/UserInfo.java +++ /dev/null @@ -1,95 +0,0 @@ -package security.entities; - -import java.io.Serializable; - -public class UserInfo implements Serializable{ - - private static final long serialVersionUID = 1225151430484658395L; - - //required - String id = null; - String email = null; - //non required (could be left null) - Boolean emailIsVerified = null; - String name = null; - String pictureUrl = null; - String locale = null; - String familyName = null; - String givenName = null; - - - - - public UserInfo(String id, String email, Boolean emailIsVerified, String name, String pictureUrl, String locale, String familyName, String givenName) { - this.id = id; - this.email = email; - this.emailIsVerified = emailIsVerified; - this.name = name; - this.pictureUrl = pictureUrl; - this.locale = locale; - this.familyName = familyName; - this.givenName = givenName; - } - - - - 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; - } - - - - @Override - public String toString() { - return "UserInfo [id=" + id + ", email=" + email + ", emailIsVerified=" + emailIsVerified + ", name=" + name - + ", pictureUrl=" + pictureUrl + ", locale=" + locale + ", familyName=" + familyName + ", givenName=" - + givenName + "]"; - } - - -} diff --git a/dmp-backend/src/main/webapp/WEB-INF/applicationContext.xml b/dmp-backend/src/main/webapp/WEB-INF/applicationContext.xml index a9f365b42..0f6721e4b 100644 --- a/dmp-backend/src/main/webapp/WEB-INF/applicationContext.xml +++ b/dmp-backend/src/main/webapp/WEB-INF/applicationContext.xml @@ -95,6 +95,7 @@ +