poprawione logowanie poprzez USOS

This commit is contained in:
unknown 2019-11-28 18:36:26 +01:00
parent a2666f0f05
commit bd6c1e5006
8 changed files with 133 additions and 30 deletions

View File

@ -19,6 +19,13 @@
</properties> </properties>
<dependencies> <dependencies>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <artifactId>spring-boot-starter</artifactId>

View File

@ -15,6 +15,7 @@ import studycave.studycaverestservice.model.user.User;
import studycave.studycaverestservice.usos.AuthorizationService; import studycave.studycaverestservice.usos.AuthorizationService;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -43,29 +44,14 @@ public class UsosController {
String oauth_verifier = request.getHeader("oauth_verifier"); String oauth_verifier = request.getHeader("oauth_verifier");
try { try {
return ResponseEntity.status(HttpStatus.OK).headers(responseHeaders).body(authorizationService.authorize(oauth_token, oauth_token_secret, oauth_verifier)); String responseToken = authorizationService.authorize(oauth_token, oauth_token_secret, oauth_verifier);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) { 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()); 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<Object> 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") @GetMapping("/request_token")
public ResponseEntity<String> getToken(@RequestParam(required = false, defaultValue = "oob") String oauth_callback) { public ResponseEntity<String> getToken(@RequestParam(required = false, defaultValue = "oob") String oauth_callback) {
HttpHeaders responseHeaders = new HttpHeaders(); HttpHeaders responseHeaders = new HttpHeaders();

View File

@ -36,6 +36,9 @@ public class User {
@Column(unique=true) @Column(unique=true)
private String email; private String email;
@OneToOne(cascade = CascadeType.ALL)
private UsosUser usosUser;
@OneToMany(mappedBy="user",cascade = CascadeType.ALL) @OneToMany(mappedBy="user",cascade = CascadeType.ALL)
List<StudyGroupMember> groupMembers = new ArrayList<>(); List<StudyGroupMember> groupMembers = new ArrayList<>();

View File

@ -4,6 +4,7 @@ import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@ -11,9 +12,11 @@ import static java.util.Collections.emptyList;
@Service @Service
public class UserDetailsServiceImpl implements UserDetailsService { public class UserDetailsServiceImpl implements UserDetailsService {
private UserRepository applicationUserRepository; private UserRepository applicationUserRepository;
private BCryptPasswordEncoder bCryptPasswordEncoder;
public UserDetailsServiceImpl(UserRepository applicationUserRepository) { public UserDetailsServiceImpl(UserRepository applicationUserRepository, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.applicationUserRepository = applicationUserRepository; this.applicationUserRepository = applicationUserRepository;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
} }
@Override @Override
@ -22,6 +25,9 @@ public class UserDetailsServiceImpl implements UserDetailsService {
if (applicationUser == null) { if (applicationUser == null) {
throw new UsernameNotFoundException(username); throw new UsernameNotFoundException(username);
} }
if (applicationUser.getUsosUser() != null)
applicationUser.setPassword(applicationUser.getUsosUser().getPassword());
return new User(applicationUser.getUsername(), applicationUser.getPassword(), emptyList()); return new User(applicationUser.getUsername(), applicationUser.getPassword(), emptyList());
} }
} }

View File

@ -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;
}

View File

@ -45,6 +45,8 @@ public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilte
studycave.studycaverestservice.model.user.User creds = new ObjectMapper() studycave.studycaverestservice.model.user.User creds = new ObjectMapper()
.readValue(req.getInputStream(), studycave.studycaverestservice.model.user.User.class); .readValue(req.getInputStream(), studycave.studycaverestservice.model.user.User.class);
// if ()
return authenticationManager.authenticate( return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken( new UsernamePasswordAuthenticationToken(
creds.getUsername(), creds.getUsername(),

View File

@ -3,33 +3,53 @@ package studycave.studycaverestservice.usos;
import io.restassured.response.Response; import io.restassured.response.Response;
import org.apache.commons.codec.binary.Base64; 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.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.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.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject; import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import studycave.studycaverestservice.PropertiesLoader; import studycave.studycaverestservice.PropertiesLoader;
import studycave.studycaverestservice.model.user.User; import studycave.studycaverestservice.model.user.User;
import studycave.studycaverestservice.model.user.UserRepository; 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.Mac;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import static io.restassured.RestAssured.get; import static io.restassured.RestAssured.get;
import static io.restassured.RestAssured.when; import static io.restassured.RestAssured.when;
import static studycave.studycaverestservice.utils.PasswordGenerator.*;
@Service @Service
public class AuthorizationService { public class AuthorizationService {
private BCryptPasswordEncoder bCryptPasswordEncoder;
public AuthorizationService(BCryptPasswordEncoder bCryptPasswordEncoder) {
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
private static final String ENC = "UTF-8"; private static final String ENC = "UTF-8";
private static final String HMAC_SHA1 = "HmacSHA1"; private static final String HMAC_SHA1 = "HmacSHA1";
private static Base64 base64 = new Base64(); private static Base64 base64 = new Base64();
@ -39,7 +59,7 @@ public class AuthorizationService {
@Autowired @Autowired
private UserRepository userRepository; 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<NameValuePair> queryParams = new ArrayList<>(); List<NameValuePair> queryParams = new ArrayList<>();
queryParams.add(new BasicNameValuePair("oauth_consumer_key", propertiesLoader.getKey())); queryParams.add(new BasicNameValuePair("oauth_consumer_key", propertiesLoader.getKey()));
queryParams.add(new BasicNameValuePair("oauth_nonce", "" + (int) (Math.random() * 100000000))); 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); 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)); queryParams.add(new BasicNameValuePair("oauth_signature", oauth_signature));
String url = "/oauth/access_token?" + URLEncodedUtils.format(queryParams, ENC); String url = "/oauth/access_token?" + URLEncodedUtils.format(queryParams, ENC);
String response = when().get(url).body().asString();
return 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 { public String requestToken(String oauth_callback) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException {
@ -89,7 +115,7 @@ public class AuthorizationService {
return loggedOut; 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<NameValuePair> queryParams = new ArrayList<>(); List<NameValuePair> queryParams = new ArrayList<>();
queryParams.add(new BasicNameValuePair("oauth_consumer_key", propertiesLoader.getKey())); queryParams.add(new BasicNameValuePair("oauth_consumer_key", propertiesLoader.getKey()));
queryParams.add(new BasicNameValuePair("oauth_nonce", "" + (int) (Math.random() * 100000000))); queryParams.add(new BasicNameValuePair("oauth_nonce", "" + (int) (Math.random() * 100000000)));
@ -108,11 +134,25 @@ public class AuthorizationService {
id = responseJSON.getString("id"); id = responseJSON.getString("id");
//User user = getUserFromDB(id);
User user = new User(); Optional<User> userCheck = userRepository.findByUsername(id);
user.setName(responseJSON.getString("first_name")); String generatedPassword = PasswordGenerator.generatePassword(16, ALPHA_CAPS + ALPHA + NUMERIC);
user.setSurname(responseJSON.getString("last_name")); if (!userCheck.isPresent()) {
return userRepository.save(user); 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( return new String(base64.encode(mac.doFinal(base.toString().getBytes(
ENC))), ENC).trim(); 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;
}
} }

View File

@ -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();
}
}