Commit d00c6c7c authored by Matija Obreza's avatar Matija Obreza

Fixed login with Google+

parent 34317a70
......@@ -52,7 +52,7 @@ public interface UserService {
User getUserById(long userId) throws UserException;
boolean exists(String username) throws UserException;
boolean exists(String username);
Page<UserWrapper> listWrapped(int startRow, int pageSize) throws UserException;
......@@ -71,7 +71,7 @@ public interface UserService {
void setAccountLockLocal(String uuid, boolean locked);
void userEmailValidated(String uuid) throws UserException;
void userEmailValidated(String uuid);
void googleAuthentication(GoogleUserInfo userInfo) throws UserException;
void googleAuthentication(GoogleUserInfo userInfo);
}
......@@ -125,11 +125,9 @@ public class EMailVerificationServiceImpl implements EMailVerificationService {
// Remove token
verificationTokenRepository.delete(verificationToken);
return true;
} catch (UserException e) {
LOG.error(e.getMessage(), e);
} catch (NullPointerException e) {
LOG.error(e, e);
}
return false;
}
......
......@@ -75,7 +75,7 @@ public class UserServiceImpl implements UserService {
@Override
// FIXME Re-enable this
//@PreAuthorize("hasRole('ADMINISTRATOR')")
// @PreAuthorize("hasRole('ADMINISTRATOR')")
public Page<User> listUsers(Pageable pageable) {
return userPersistence.findAll(pageable);
}
......@@ -323,13 +323,13 @@ public class UserServiceImpl implements UserService {
}
@Override
public boolean exists(String username) throws UserException {
public boolean exists(String username) {
return userPersistence.findByEmail(username) != null;
}
@Override
@Transactional
public void userEmailValidated(String uuid) throws UserException {
public void userEmailValidated(String uuid) {
LOG.info("Validating user email for uuid=" + uuid);
User user = userPersistence.findByUuid(uuid);
......@@ -341,30 +341,35 @@ public class UserServiceImpl implements UserService {
// Since it's a set, we can just add
userRoles.add(UserRole.VALIDATEDUSER);
addRoleToCurrentUser(user, UserRole.VALIDATEDUSER.getName());
updateUser(user);
LOG.info("Ensured VALIDATEDUSER role for user " + user);
try {
updateUser(user);
addRoleToCurrentUser(user, UserRole.VALIDATEDUSER.getName());
LOG.info("Ensured VALIDATEDUSER role for user " + user);
} catch (UserException e) {
LOG.error(e);
}
}
@Override
public void googleAuthentication(GoogleUserInfo userInfo) throws UserException {
User user=getUserByEmail(userInfo.getEmail());
userEmailValidated(user.getUuid());
@Override
public void googleAuthentication(GoogleUserInfo userInfo) {
User user = getUserByEmail(userInfo.getEmail());
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("USER"));
grantedAuthorities.add(new SimpleGrantedAuthority("VALIDATEDUSER"));
if (user == null) {
LOG.warn("Authentication with Google+ failed: No such user " + userInfo.getEmail());
}
AuthUserDetails userDetails = new AuthUserDetails(user.getUuid(), user.getPassword() , grantedAuthorities);
userDetails.setUser(user);
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("USER"));
grantedAuthorities.add(new SimpleGrantedAuthority("VALIDATEDUSER"));
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
AuthUserDetails userDetails = new AuthUserDetails(user.getUuid(), user.getPassword(), grantedAuthorities);
userDetails.setUser(user);
}
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
private void addRoleToCurrentUser(User user, String role) {
private void addRoleToCurrentUser(User user, String role) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof AuthUserDetails) {
......
package org.genesys2.server.servlet.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.RandomStringUtils;
import org.genesys2.server.exception.UserException;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.EMailVerificationService;
import org.genesys2.server.service.UserService;
import org.genesys2.server.servlet.util.GoogleOAuthUtil;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.social.google.api.Google;
import org.springframework.social.google.api.impl.GoogleTemplate;
import org.springframework.social.google.api.userinfo.GoogleUserInfo;
......@@ -17,54 +18,47 @@ import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@RequestMapping("/g")
public class GoogleSocialController extends BaseController {
@Value("${google.auth.url}")
private String url;
@Autowired
private UserService userService;
@Autowired
private EMailVerificationService emailService;
@Autowired
private GoogleOAuthUtil oAuth;
@Autowired
private UserService userService;
@RequestMapping("/login")
public void redirectToGoogle(HttpServletResponse response) throws IOException {
response.sendRedirect(url);
}
@Autowired
private GoogleOAuthUtil googleOAuthUtil;
@RequestMapping("/auth")
public String googleAuth(Model model, HttpServletRequest request) throws IOException, JSONException, UserException {
@RequestMapping("/google/login")
public void redirectToGoogle(HttpServletResponse response) throws IOException {
response.sendRedirect(googleOAuthUtil.getAuthenticationUrl());
}
@RequestMapping(GoogleOAuthUtil.LOCAL_GOOGLEAUTH_PATH)
public String googleAuth(Model model, HttpServletRequest request) {
String accessToken = oAuth.exchangeForAccessToken(request);
String accessToken = null;
try {
accessToken = googleOAuthUtil.exchangeForAccessToken(request);
} catch (IOException | JSONException e) {
_logger.warn(e.getMessage(), e);
}
if (accessToken == null) {
model.addAttribute("error", true);
return "/login";
}
if (accessToken == null) {
model.addAttribute("error", true);
return "/login";
}
Google google = new GoogleTemplate(accessToken);
GoogleUserInfo userInfo = google.userOperations().getUserInfo();
Google google = new GoogleTemplate(accessToken);
GoogleUserInfo userInfo = google.userOperations().getUserInfo();
if (!userService.exists(userInfo.getEmail())) {
String pwd = RandomStringUtils.randomAlphanumeric(10);
User user = userService.createAccount(userInfo.getEmail(), pwd, userInfo.getName());
emailService.sendPasswordForGenesysAccount(user, pwd);
}
if (!userService.exists(userInfo.getEmail())) {
String pwd = RandomStringUtils.randomAlphanumeric(20);
User user = userService.createAccount(userInfo.getEmail(), pwd, userInfo.getName());
userService.userEmailValidated(user.getUuid());
}
userService.googleAuthentication(userInfo);
userService.googleAuthentication(userInfo);
return "redirect:/profile";
}
return "redirect:/";
}
}
......@@ -16,6 +16,11 @@
package org.genesys2.server.servlet.controller;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.genesys2.server.model.Permissions;
import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.impl.User;
......@@ -27,6 +32,7 @@ import org.genesys2.server.service.UserService;
import org.genesys2.util.ReCaptchaUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
......@@ -36,14 +42,6 @@ import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
/**
* Controller which simply handles *.html requests
*/
......
package org.genesys2.server.servlet.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
@Component
public class GoogleOAuthUtil {
private String clientId;
private String secret;
private String redirectUrl;
public String exchangeForAccessToken(HttpServletRequest request) throws IOException, JSONException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://accounts.google.com/o/oauth2/token");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("code", request.getParameter("code")));
params.add(new BasicNameValuePair("client_id", clientId));
params.add(new BasicNameValuePair("client_secret", secret));
params.add(new BasicNameValuePair("redirect_uri", redirectUrl));
params.add(new BasicNameValuePair("grant_type", "authorization_code"));
params.add(new BasicNameValuePair("scope", ""));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse response = httpclient.execute(httppost);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String line = null; (line = reader.readLine()) != null; ) {
builder.append(line).append("\n");
}
JSONObject jsonObject = new JSONObject(builder.toString());
return jsonObject.getString("access_token") != null ? jsonObject.getString("access_token") : null;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setSecret(String secret) {
this.secret = secret;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public static final String LOCAL_GOOGLEAUTH_PATH = "/google/auth";
@Value("${base.url}")
private String baseUrl;
@Value("${google.consumerKey}")
private String googleApiClientId;
@Value("${google.consumerSecret}")
private String secret;
public String exchangeForAccessToken(HttpServletRequest request) throws IOException, JSONException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://accounts.google.com/o/oauth2/token");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("code", request.getParameter("code")));
params.add(new BasicNameValuePair("client_id", googleApiClientId));
params.add(new BasicNameValuePair("client_secret", secret));
params.add(new BasicNameValuePair("redirect_uri", baseUrl + LOCAL_GOOGLEAUTH_PATH));
params.add(new BasicNameValuePair("grant_type", "authorization_code"));
params.add(new BasicNameValuePair("scope", ""));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse response = httpclient.execute(httppost);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String line = null; (line = reader.readLine()) != null;) {
builder.append(line).append("\n");
}
JSONObject jsonObject = new JSONObject(builder.toString());
return jsonObject.has("access_token") ? jsonObject.getString("access_token") : null;
}
public String getAuthenticationUrl() {
// google.auth.url=https://accounts.google.com/o/oauth2/auth?redirect_uri=http://localhost:8080/g/auth&response_type=code&client_id=12345-hfp8qjfeqaefpitbc707uluuh8vq65k7.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.me+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&approval_prompt=auto&access_type=online&include_granted_scopes=true
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
parameters.add(new BasicNameValuePair("redirect_uri", baseUrl + LOCAL_GOOGLEAUTH_PATH));
parameters.add(new BasicNameValuePair("response_type", "code"));
parameters.add(new BasicNameValuePair("client_id", googleApiClientId));
parameters.add(new BasicNameValuePair("approval_prompt", "auto"));
parameters.add(new BasicNameValuePair("access_type", "online"));
parameters.add(new BasicNameValuePair("include_granted_scopes", "true"));
// Google+ "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"));
// Only basic:
parameters.add(new BasicNameValuePair("scope", "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"));
String query = URLEncodedUtils.format(parameters, "UTF-8");
return "https://accounts.google.com/o/oauth2/auth?" + query;
}
}
......@@ -36,6 +36,7 @@ login.login-button=Login
login.register-now=Create an account
logout=Logout
login.forgot-password=Forgot password
login.with-google-plus=Login with Google+
# Registration
registration.page.title=Create a user account
......
......@@ -31,6 +31,5 @@
<import resource="spring-security-acl.xml" />
<import resource="spring-security.xml" />
<import resource="spring-mail.xml" />
<import resource="spring-social.xml" />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 Global Crop Diversity Trust
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd"
default-autowire="no">
<context:component-scan base-package="org.genesys2.server"/>
<context:property-placeholder ignore-resource-not-found="true" location="classpath:/spring/spring.properties"/>
<bean name="googleOAuthUtil" class="org.genesys2.server.servlet.util.GoogleOAuthUtil">
<property name="clientId" value="${google.consumerKey}"/>
<property name="secret" value="${google.consumerSecret}"/>
<property name="redirectUrl" value="${google.redirect.url}"/>
</bean>
</beans>
\ No newline at end of file
......@@ -16,12 +16,12 @@
base.url=http://localhost:8080
db.url=jdbc:mysql://localhost/genesys2
db.url=jdbc:mysql://localhost/genesys4?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
db.driverClassName = com.mysql.jdbc.Driver
db.username = root
db.password = 1
db.password =
db.showSql=false
db.hbm2ddl=update
db.hbm2ddl=do-nothing
c3p0.acquireIncrement=1
c3p0.minPoolSize=1
......@@ -75,8 +75,7 @@ mail.debug.message= Email has been sent succesfully\n\
\n\n==================================
#google properties
google.consumerKey=534251255050-3o55n707i6fare7kcad32u6gs7r7t8h8.apps.googleusercontent.com
google.consumerSecret=tjbSs5iDFVeoNB7_mXX0M1dO
google.redirect.url=http://localhost:8080/g/auth
google.auth.url=https://accounts.google.com/o/oauth2/auth?redirect_uri=http://localhost:8080/g/auth&response_type=code&client_id=534251255050-3o55n707i6fare7kcad32u6gs7r7t8h8.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.me+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&approval_prompt=auto&access_type=online&include_granted_scopes=true
google.consumerKey=
google.consumerSecret=
......@@ -37,9 +37,9 @@
</div>
<button type="submit" class="btn btn-green"><spring:message
code="login.login-button"/></button>
<a href="<c:url value="/g/login" />" class="btn btn-danger">Google+</a>
<span class="or"></span>
<a href="<c:url value="/registration" />" class="btn btn-default"><spring:message code="login.register-now"/></a>
<span class="or">-</span>
<a href="<c:url value="/google/login" />" class="btn btn-default google-signin"><spring:message code="login.with-google-plus"/></a>
<a href="<c:url value="/registration" />" class="btn btn-default"><spring:message code="login.register-now"/></a>
</form>
</li>
</ul>
......
......@@ -14,6 +14,7 @@
<c:if test="${error}">
<div class="alert alert-danger"><spring:message code="login.invalid-token"/></div>
</c:if>
<form role="form" method="POST" action="/login-attempt" class="form-horizontal">
<div class="form-group">
<label for="j_username" class="col-lg-2 control-label"><spring:message code="login.username"/></label>
......@@ -40,6 +41,7 @@
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<input type="submit" value="<spring:message code="login.login-button" />" class="btn btn-primary" />
<a href="<c:url value="/google/login" />" class="btn btn-default google-signin"><spring:message code="login.with-google-plus"/></a>
<a href="registration" id="registration" class="btn btn-default"><spring:message code="login.register-now"/></a>
<a href="forgot-password" id="forgot-password" class="btn"><spring:message code="login.forgot-password"/></a>
</div>
......
......@@ -213,32 +213,6 @@ html[dir="rtl"] #header .nav .dropdown-menu .checkbox {
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#88ba42', endColorstr='#accf7b',GradientType=0 );
}
#header .nav .dropdown-menu .btn-danger {
background: #d9534f;
background: -moz-linear-gradient(top, #d9534f 0%, #d9534f 50%, #c12e2a 51%, #c12e2a 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#d9534f), color-stop(50%,#d9534f), color-stop(51%,#c12e2a), color-stop(100%,#c12e2a));
background: -webkit-linear-gradient(top, #d9534f 0%,#d9534f 50%,#c12e2a 51%,#c12e2a 100%);
background: -o-linear-gradient(top, #d9534f 0%,#d9534f 50%,#c12e2a 51%,#c12e2a 100%);
background: -ms-linear-gradient(top, #d9534f 0%,#d9534f 50%,#c12e2a 51%,#c12e2a 100%);
background: linear-gradient(to bottom, #d9534f 0%,#d9534f 50%,#c12e2a 51%,#c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d9534f', endColorstr='#c12e2a',GradientType=0 );
color:#2b2924;
font-size:16px;
font-weight:bold;
margin:0 20px;
width:200px;
}
#header .nav .dropdown-menu .btn-danger:hover {
background: #c12e2a;
background: -moz-linear-gradient(top, #c12e2a 0%, #c12e2a 50%, #d9534f 51%, #d9534f 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c12e2a), color-stop(50%,#c12e2a), color-stop(51%,#d9534f), color-stop(100%,#d9534f));
background: -webkit-linear-gradient(top, #c12e2a 0%,#c12e2a 50%,#d9534f 51%,#d9534f 100%);
background: -o-linear-gradient(top, #c12e2a 0%,#c12e2a 50%,#d9534f 51%,#d9534f 100%);
background: -ms-linear-gradient(top, #c12e2a 0%,#c12e2a 50%,#d9534f 51%,#d9534f 100%);
background: linear-gradient(to bottom, #c12e2a 0%,#c12e2a 50%,#d9534f 51%,#d9534f 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c12e2a', endColorstr='#d9534f',GradientType=0 );
}
#header .nav .dropdown-menu .btn-default {
background:#e8e8e8;
......@@ -1834,4 +1808,11 @@ html[dir="rtl"] ul.statistics .stats-number {
margin-top: 2em;
margin-left: 0;
font-size: 80%;
}
\ No newline at end of file
}
#header .nav .dropdown-menu .google-signin, #header .nav .dropdown-menu .google-signin:hover, #header .nav .dropdown-menu .google-signin:active, .google-signin, .google-signin:active {
background-image: url('../images/google-signin.png');
background-repeat: no-repeat;
background-position: 0 0;
padding-left: 30px;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment