diff --git a/BackEnd/pom.xml b/BackEnd/pom.xml index 89ab3c0..9c2eff9 100644 --- a/BackEnd/pom.xml +++ b/BackEnd/pom.xml @@ -29,7 +29,34 @@ commons-text 1.8 + + io.rest-assured + spring-mock-mvc + 3.1.1 + test + + + + org.json + json + 20190722 + + + io.rest-assured + json-path + 3.1.1 + + + io.rest-assured + rest-assured + + + io.rest-assured + rest-assured + 3.1.1 + test + org.springframework.boot @@ -90,6 +117,10 @@ + + io.rest-assured + rest-assured + diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/PropertiesLoader.java b/BackEnd/src/main/java/studycave/studycaverestservice/PropertiesLoader.java new file mode 100644 index 0000000..b6c1ec6 --- /dev/null +++ b/BackEnd/src/main/java/studycave/studycaverestservice/PropertiesLoader.java @@ -0,0 +1,43 @@ +package studycave.studycaverestservice; + +import io.restassured.RestAssured; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class PropertiesLoader { + + @Value("${usos.baseURI}") + private String usosBaseURI; + + @Value("${usos.basePath}") + private String usosBasePath; + + @Value("${usos.port}") + private int usosPort; + + @Value("${application.key}") + private String key; + + @Value("${application.secret}") + private String secret; + + public void initUsosInstance() { + RestAssured.baseURI = usosBaseURI; + RestAssured.basePath = usosBasePath; + RestAssured.port = usosPort; + } + + public String getUsosApiURL() { + return usosBaseURI + usosBasePath; + } + + public String getKey() { + return key; + } + + public String getSecret() { + return secret; + } + +} diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/StudycaveRestServiceApplication.java b/BackEnd/src/main/java/studycave/studycaverestservice/StudycaveRestServiceApplication.java index a9a12d3..fa141d5 100644 --- a/BackEnd/src/main/java/studycave/studycaverestservice/StudycaveRestServiceApplication.java +++ b/BackEnd/src/main/java/studycave/studycaverestservice/StudycaveRestServiceApplication.java @@ -1,14 +1,20 @@ package studycave.studycaverestservice; import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import javax.annotation.PostConstruct; + @SpringBootApplication public class StudycaveRestServiceApplication { + @Autowired + private PropertiesLoader propertiesLoader; + public static void main(String[] args) { SpringApplication.run(StudycaveRestServiceApplication.class, args); } @@ -23,4 +29,9 @@ public class StudycaveRestServiceApplication { return new ModelMapper(); } + @PostConstruct + private void LoadData() { + propertiesLoader.initUsosInstance(); + } + } diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/controller/UsosController.java b/BackEnd/src/main/java/studycave/studycaverestservice/controller/UsosController.java new file mode 100644 index 0000000..68e3f82 --- /dev/null +++ b/BackEnd/src/main/java/studycave/studycaverestservice/controller/UsosController.java @@ -0,0 +1,79 @@ +package studycave.studycaverestservice.controller; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import studycave.studycaverestservice.PropertiesLoader; +import studycave.studycaverestservice.model.user.User; +import studycave.studycaverestservice.usos.AuthorizationService; + +import javax.servlet.http.HttpServletRequest; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +@RestController +@RequestMapping("/usos") +public class UsosController { + + private static final String ENC = "UTF-8"; + @Autowired + private AuthorizationService authorizationService; + @Autowired + private PropertiesLoader propertiesLoader; + + @GetMapping("/access_token") + @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"), + @ApiImplicitParam(name = "oauth_verifier", value = "User's oauth_verifier", required = true, dataType = "string", paramType = "header") + }) + public ResponseEntity authorize(HttpServletRequest request) { + HttpHeaders responseHeaders = new HttpHeaders(); + + String oauth_token = request.getHeader("oauth_token"); + String oauth_token_secret = request.getHeader("oauth_token_secret"); + 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) { + 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(); + try { + return ResponseEntity.status(HttpStatus.OK).headers(responseHeaders).body(authorizationService.requestToken(oauth_callback)); + } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).headers(responseHeaders).body(e.getCause().toString()); + } + } + +} diff --git a/BackEnd/src/main/java/studycave/studycaverestservice/usos/AuthorizationService.java b/BackEnd/src/main/java/studycave/studycaverestservice/usos/AuthorizationService.java new file mode 100644 index 0000000..f74e4ca --- /dev/null +++ b/BackEnd/src/main/java/studycave/studycaverestservice/usos/AuthorizationService.java @@ -0,0 +1,143 @@ +package studycave.studycaverestservice.usos; + + +import io.restassured.response.Response; +import org.apache.commons.codec.binary.Base64; +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.message.BasicNameValuePair; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +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 javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +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 static io.restassured.RestAssured.get; +import static io.restassured.RestAssured.when; + +@Service +public class AuthorizationService { + + private static final String ENC = "UTF-8"; + private static final String HMAC_SHA1 = "HmacSHA1"; + private static Base64 base64 = new Base64(); + @Autowired + private PropertiesLoader propertiesLoader; + + @Autowired + private UserRepository userRepository; + + public String authorize(String oauth_token, String oauth_token_secret, String oauth_verifier) throws UnsupportedEncodingException, 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))); + queryParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1")); + queryParams.add(new BasicNameValuePair("oauth_timestamp", "" + (System.currentTimeMillis() / 1000))); + queryParams.add(new BasicNameValuePair("oauth_token", oauth_token)); + queryParams.add(new BasicNameValuePair("oauth_verifier", oauth_verifier)); + queryParams.add(new BasicNameValuePair("oauth_version", "1.0")); + 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(); + } + + public String requestToken(String oauth_callback) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException { + List queryParams = new ArrayList<>(); + queryParams.add(new BasicNameValuePair("oauth_callback", oauth_callback)); + queryParams.add(new BasicNameValuePair("oauth_consumer_key", propertiesLoader.getKey())); + queryParams.add(new BasicNameValuePair("oauth_nonce", "" + (int) (Math.random() * 100000000))); + queryParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1")); + queryParams.add(new BasicNameValuePair("oauth_timestamp", "" + (System.currentTimeMillis() / 1000))); + queryParams.add(new BasicNameValuePair("oauth_version", "1.0")); + String oauth_signature = getSignature("GET", URLEncoder.encode(propertiesLoader.getUsosApiURL() + "/oauth/request_token", ENC), URLEncoder.encode(URLEncodedUtils.format(queryParams, ENC), ENC), ""); + queryParams.add(new BasicNameValuePair("oauth_signature", oauth_signature)); + String url = "/oauth/request_token?" + URLEncodedUtils.format(queryParams, ENC); + + String tokens = when().get(url).body().asString(); + + return propertiesLoader.getUsosApiURL() + "/oauth/authorize?" + tokens; + } + + public String logOut(String oauth_token, String oauth_token_secret) throws UnsupportedEncodingException, 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))); + queryParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1")); + queryParams.add(new BasicNameValuePair("oauth_timestamp", "" + (System.currentTimeMillis() / 1000))); + queryParams.add(new BasicNameValuePair("oauth_token", oauth_token)); + queryParams.add(new BasicNameValuePair("oauth_version", "1.0")); + String oauth_signature = getSignature("GET", URLEncoder.encode(propertiesLoader.getUsosApiURL() + "/oauth/revoke_token", ENC), URLEncoder.encode(URLEncodedUtils.format(queryParams, ENC), ENC), oauth_token_secret); + queryParams.add(new BasicNameValuePair("oauth_signature", oauth_signature)); + String url = "/oauth/revoke_token?" + URLEncodedUtils.format(queryParams, ENC); + + String loggedOut = when().get(url).body().asString(); + + return loggedOut; + } + + public User checkUserDetails(String oauth_token, String oauth_token_secret) throws UnsupportedEncodingException, 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))); + queryParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1")); + queryParams.add(new BasicNameValuePair("oauth_timestamp", "" + (System.currentTimeMillis() / 1000))); + queryParams.add(new BasicNameValuePair("oauth_token", oauth_token)); + queryParams.add(new BasicNameValuePair("oauth_version", "1.0")); + String oauth_signature = getSignature("GET", URLEncoder.encode(propertiesLoader.getUsosApiURL() + "/users/user", ENC), URLEncoder.encode(URLEncodedUtils.format(queryParams, ENC), ENC), oauth_token_secret); + + queryParams.add(new BasicNameValuePair("oauth_signature", oauth_signature)); + String url = "/users/user?" + URLEncodedUtils.format(queryParams, ENC); + + Response response = get(url); + JSONObject responseJSON = new JSONObject(response.getBody().print()); + String id = null; + + 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); + } + + + + + public String getSignature(String method, String url, String params, String secret_token) + throws UnsupportedEncodingException, NoSuchAlgorithmException, + InvalidKeyException { + + StringBuilder base = new StringBuilder(); + base.append(method); + base.append("&"); + base.append(url); + base.append("&"); + base.append(params); + + byte[] keyBytes = (propertiesLoader.getSecret() + "&" + secret_token).getBytes(ENC); + + SecretKey key = new SecretKeySpec(keyBytes, HMAC_SHA1); + + Mac mac = Mac.getInstance(HMAC_SHA1); + mac.init(key); + + // encode it, base64 it, change it to string and return. + return new String(base64.encode(mac.doFinal(base.toString().getBytes( + ENC))), ENC).trim(); + } +} diff --git a/BackEnd/src/main/resources/application.properties b/BackEnd/src/main/resources/application.properties index f472171..902d768 100644 --- a/BackEnd/src/main/resources/application.properties +++ b/BackEnd/src/main/resources/application.properties @@ -5,3 +5,11 @@ spring.datasource.username=sc spring.datasource.password=L0XIcnvtWpYEnr4w spring.servlet.multipart.max-file-size=500KB spring.servlet.multipart.max-request-size=500KB + +application.key = 5z57PPmtR4wXaRZDSpUH +application.secret = ccAxvXDqLwdkPpekJrS2fdfGQ2jLnb22fa4uB5Ef + +#usos instance to use +usos.baseURI=https://usosapps.amu.edu.pl +usos.basePath=/services +usos.port=443