diff --git a/BackEnd/pom.xml b/BackEnd/pom.xml index 9c2eff9..f1e3d51 100644 --- a/BackEnd/pom.xml +++ b/BackEnd/pom.xml @@ -19,6 +19,13 @@ + + + commons-io + commons-io + 2.6 + + org.springframework.boot spring-boot-starter diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/controller/UsosController.java b/BackEnd/src/main/java/studycave/studycaverestservice/controller/UsosController.java index 68e3f82..d6c3208 100644 --- a/BackEnd/src/main/java/studycave/studycaverestservice/controller/UsosController.java +++ b/BackEnd/src/main/java/studycave/studycaverestservice/controller/UsosController.java @@ -15,6 +15,7 @@ import studycave.studycaverestservice.model.user.User; import studycave.studycaverestservice.usos.AuthorizationService; import javax.servlet.http.HttpServletRequest; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -43,29 +44,14 @@ public class UsosController { String oauth_verifier = request.getHeader("oauth_verifier"); try { - return ResponseEntity.status(HttpStatus.OK).headers(responseHeaders).body(authorizationService.authorize(oauth_token, oauth_token_secret, oauth_verifier)); - } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) { + String responseToken = authorizationService.authorize(oauth_token, oauth_token_secret, oauth_verifier); + responseHeaders.add("authorization", responseToken); + return ResponseEntity.status(HttpStatus.OK).headers(responseHeaders).body(responseToken); + } catch (NoSuchAlgorithmException | InvalidKeyException | IOException e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).headers(responseHeaders).body(e.getCause().toString()); } } - @ApiImplicitParams({ - @ApiImplicitParam(name = "oauth_token", value = "User's oauth_token", required = true, dataType = "string", paramType = "header"), - @ApiImplicitParam(name = "oauth_token_secret", value = "User's oauth_token_secret", required = true, dataType = "string", paramType = "header") - }) - @GetMapping("/details") - public ResponseEntity userDetails(HttpServletRequest request) { - HttpHeaders responseHeaders = new HttpHeaders(); - String oauth_token = request.getHeader("oauth_token"); - String oauth_token_secret = request.getHeader("oauth_token_secret"); - - try { - return ResponseEntity.status(HttpStatus.OK).headers(responseHeaders).body(authorizationService.checkUserDetails(oauth_token, oauth_token_secret)); - } catch (InvalidKeyException | UnsupportedEncodingException | NoSuchAlgorithmException e) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).headers(responseHeaders).body(e.getMessage()); - } - } - @GetMapping("/request_token") public ResponseEntity getToken(@RequestParam(required = false, defaultValue = "oob") String oauth_callback) { HttpHeaders responseHeaders = new HttpHeaders(); diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/model/user/User.java b/BackEnd/src/main/java/studycave/studycaverestservice/model/user/User.java index 562eab0..afd3698 100644 --- a/BackEnd/src/main/java/studycave/studycaverestservice/model/user/User.java +++ b/BackEnd/src/main/java/studycave/studycaverestservice/model/user/User.java @@ -36,6 +36,9 @@ public class User { @Column(unique=true) private String email; + @OneToOne(cascade = CascadeType.ALL) + private UsosUser usosUser; + @OneToMany(mappedBy="user",cascade = CascadeType.ALL) List groupMembers = new ArrayList<>(); diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/model/user/UserDetailsServiceImpl.java b/BackEnd/src/main/java/studycave/studycaverestservice/model/user/UserDetailsServiceImpl.java index 5b16035..7e44501 100644 --- a/BackEnd/src/main/java/studycave/studycaverestservice/model/user/UserDetailsServiceImpl.java +++ b/BackEnd/src/main/java/studycave/studycaverestservice/model/user/UserDetailsServiceImpl.java @@ -4,6 +4,7 @@ import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import static java.util.Collections.emptyList; @@ -11,9 +12,11 @@ import static java.util.Collections.emptyList; @Service public class UserDetailsServiceImpl implements UserDetailsService { private UserRepository applicationUserRepository; + private BCryptPasswordEncoder bCryptPasswordEncoder; - public UserDetailsServiceImpl(UserRepository applicationUserRepository) { + public UserDetailsServiceImpl(UserRepository applicationUserRepository, BCryptPasswordEncoder bCryptPasswordEncoder) { this.applicationUserRepository = applicationUserRepository; + this.bCryptPasswordEncoder = bCryptPasswordEncoder; } @Override @@ -22,6 +25,9 @@ public class UserDetailsServiceImpl implements UserDetailsService { if (applicationUser == null) { throw new UsernameNotFoundException(username); } + if (applicationUser.getUsosUser() != null) + applicationUser.setPassword(applicationUser.getUsosUser().getPassword()); + return new User(applicationUser.getUsername(), applicationUser.getPassword(), emptyList()); } } diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/model/user/UsosUser.java b/BackEnd/src/main/java/studycave/studycaverestservice/model/user/UsosUser.java new file mode 100644 index 0000000..69b3e99 --- /dev/null +++ b/BackEnd/src/main/java/studycave/studycaverestservice/model/user/UsosUser.java @@ -0,0 +1,25 @@ +package studycave.studycaverestservice.model.user; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class UsosUser { + + @Id + @Column(name="id") + private String usosId; + + private String password; + +} diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/security/JWTAuthenticationFilter.java b/BackEnd/src/main/java/studycave/studycaverestservice/security/JWTAuthenticationFilter.java index f35453d..e135dba 100644 --- a/BackEnd/src/main/java/studycave/studycaverestservice/security/JWTAuthenticationFilter.java +++ b/BackEnd/src/main/java/studycave/studycaverestservice/security/JWTAuthenticationFilter.java @@ -45,6 +45,8 @@ public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilte studycave.studycaverestservice.model.user.User creds = new ObjectMapper() .readValue(req.getInputStream(), studycave.studycaverestservice.model.user.User.class); + // if () + return authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( creds.getUsername(), diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/usos/AuthorizationService.java b/BackEnd/src/main/java/studycave/studycaverestservice/usos/AuthorizationService.java index f74e4ca..20dfca8 100644 --- a/BackEnd/src/main/java/studycave/studycaverestservice/usos/AuthorizationService.java +++ b/BackEnd/src/main/java/studycave/studycaverestservice/usos/AuthorizationService.java @@ -3,33 +3,53 @@ package studycave.studycaverestservice.usos; import io.restassured.response.Response; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; +import org.apache.http.Header; +import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import studycave.studycaverestservice.PropertiesLoader; import studycave.studycaverestservice.model.user.User; import studycave.studycaverestservice.model.user.UserRepository; -import studycave.studycaverestservice.model.user.dto.UserDTO; +import studycave.studycaverestservice.model.user.UsosUser; +import studycave.studycaverestservice.utils.PasswordGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import static io.restassured.RestAssured.get; import static io.restassured.RestAssured.when; +import static studycave.studycaverestservice.utils.PasswordGenerator.*; @Service public class AuthorizationService { + private BCryptPasswordEncoder bCryptPasswordEncoder; + + public AuthorizationService(BCryptPasswordEncoder bCryptPasswordEncoder) { + this.bCryptPasswordEncoder = bCryptPasswordEncoder; + } + private static final String ENC = "UTF-8"; private static final String HMAC_SHA1 = "HmacSHA1"; private static Base64 base64 = new Base64(); @@ -39,7 +59,7 @@ public class AuthorizationService { @Autowired private UserRepository userRepository; - public String authorize(String oauth_token, String oauth_token_secret, String oauth_verifier) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException { + public String authorize(String oauth_token, String oauth_token_secret, String oauth_verifier) throws IOException, InvalidKeyException, NoSuchAlgorithmException { List queryParams = new ArrayList<>(); queryParams.add(new BasicNameValuePair("oauth_consumer_key", propertiesLoader.getKey())); queryParams.add(new BasicNameValuePair("oauth_nonce", "" + (int) (Math.random() * 100000000))); @@ -51,8 +71,14 @@ public class AuthorizationService { String oauth_signature = getSignature("GET", URLEncoder.encode(propertiesLoader.getUsosApiURL() + "/oauth/access_token", ENC), URLEncoder.encode(URLEncodedUtils.format(queryParams, ENC), ENC), oauth_token_secret); queryParams.add(new BasicNameValuePair("oauth_signature", oauth_signature)); String url = "/oauth/access_token?" + URLEncodedUtils.format(queryParams, ENC); - - return when().get(url).body().asString(); + String response = when().get(url).body().asString(); + if (response.contains("oauth_token") && response.contains("oauth_token_secret") && response.contains("&")) { + String[] tokens = response.split("&"); + oauth_token = tokens[0].replace("oauth_token=", ""); + oauth_token_secret = tokens[1].replace("oauth_token_secret=", ""); + return createUserAccountAndReturnHeaderToken(oauth_token, oauth_token_secret); + } + return "authorization failed"; } public String requestToken(String oauth_callback) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException { @@ -89,7 +115,7 @@ public class AuthorizationService { return loggedOut; } - public User checkUserDetails(String oauth_token, String oauth_token_secret) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException { + private String createUserAccountAndReturnHeaderToken(String oauth_token, String oauth_token_secret) throws IOException, InvalidKeyException, NoSuchAlgorithmException { List queryParams = new ArrayList<>(); queryParams.add(new BasicNameValuePair("oauth_consumer_key", propertiesLoader.getKey())); queryParams.add(new BasicNameValuePair("oauth_nonce", "" + (int) (Math.random() * 100000000))); @@ -108,11 +134,25 @@ public class AuthorizationService { id = responseJSON.getString("id"); - //User user = getUserFromDB(id); - User user = new User(); - user.setName(responseJSON.getString("first_name")); - user.setSurname(responseJSON.getString("last_name")); - return userRepository.save(user); + + Optional userCheck = userRepository.findByUsername(id); + String generatedPassword = PasswordGenerator.generatePassword(16, ALPHA_CAPS + ALPHA + NUMERIC); + if (!userCheck.isPresent()) { + User user = new User(); + UsosUser usosUser = new UsosUser(id, bCryptPasswordEncoder.encode(generatedPassword)); + user.setUsosUser(usosUser); + user.setName(responseJSON.getString("first_name")); + user.setSurname(responseJSON.getString("last_name")); + user.setUsername(id); + user = userRepository.save(user); + return getAuthToken(user.getUsername(), generatedPassword); + } + else { + User user = userCheck.get(); + user.getUsosUser().setPassword(bCryptPasswordEncoder.encode(generatedPassword)); + user = userRepository.save(user); + return getAuthToken(user.getUsername(), generatedPassword); + } } @@ -140,4 +180,15 @@ public class AuthorizationService { return new String(base64.encode(mac.doFinal(base.toString().getBytes( ENC))), ENC).trim(); } + + private String getAuthToken(String username, String password) throws IOException { + HttpClient httpClient = HttpClientBuilder.create().build(); + HttpPost request = new HttpPost("http://localhost:8080/login"); + StringEntity params = new StringEntity("{\"username\":\"" + username + "\",\"password\":\"" + password + "\"} "); + request.addHeader("content-type", "application/json"); + request.setEntity(params); + HttpResponse httpResponse = httpClient.execute(request); + String auth = httpResponse.getFirstHeader("authorization").getValue(); + return auth; + } } diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/utils/PasswordGenerator.java b/BackEnd/src/main/java/studycave/studycaverestservice/utils/PasswordGenerator.java new file mode 100644 index 0000000..cf3b65f --- /dev/null +++ b/BackEnd/src/main/java/studycave/studycaverestservice/utils/PasswordGenerator.java @@ -0,0 +1,23 @@ +package studycave.studycaverestservice.utils; + +import java.security.SecureRandom; + +public class PasswordGenerator { + + private static SecureRandom random = new SecureRandom(); + + + public static final String ALPHA_CAPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + public static final String ALPHA = "abcdefghijklmnopqrstuvwxyz"; + public static final String NUMERIC = "0123456789"; + public static final String SPECIAL_CHARS = "!@#$%^&*_=+-/"; + + public static String generatePassword(int len, String dic) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < len; i++) { + int index = random.nextInt(dic.length()); + result.append(dic.charAt(index)); + } + return result.toString(); + } +}