diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a2bf131..b09929f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sun Apr 12 12:33:03 CEST 2020 +distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-bin.zip -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/socket_test.html b/socket_test.html index 687388b..91399e5 100644 --- a/socket_test.html +++ b/socket_test.html @@ -1,40 +1,43 @@ - + - - -
-

Waiting for authentication...

-
- - + + + + diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/AuthenticationMessageListener.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/AuthenticationMessageListener.java deleted file mode 100644 index 89415aa..0000000 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/AuthenticationMessageListener.java +++ /dev/null @@ -1,95 +0,0 @@ -package ch.usi.inf.sa4.sanmarinoes.smarthut.socket; - -import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonConfig; -import ch.usi.inf.sa4.sanmarinoes.smarthut.config.JWTTokenUtils; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository; -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import io.jsonwebtoken.ExpiredJwtException; -import java.io.IOException; -import java.util.Map; -import java.util.function.BiConsumer; -import javax.websocket.MessageHandler; -import javax.websocket.Session; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** Generates MessageHandlers for unauthenticated socket sessions */ -@Component -public class AuthenticationMessageListener { - - private Gson gson = GsonConfig.gson(); - - private JWTTokenUtils jwtTokenUtils; - - private UserRepository userRepository; - - @Autowired - public AuthenticationMessageListener( - JWTTokenUtils jwtTokenUtils, UserRepository userRepository) { - this.jwtTokenUtils = jwtTokenUtils; - this.userRepository = userRepository; - } - - /** - * Generates a new message handler to handle socket authentication - * - * @param session the session to which authentication must be checked - * @param authorizedSetter function to call once user is authenticated - * @return a new message handler to handle socket authentication - */ - MessageHandler.Whole newHandler( - final Session session, BiConsumer authorizedSetter) { - return new MessageHandler.Whole<>() { - @Override - public void onMessage(final String message) { - if (message == null) { - acknowledge(false); - return; - } - - String token; - String username; - - try { - token = gson.fromJson(message, JsonObject.class).get("token").getAsString(); - username = jwtTokenUtils.getUsernameFromToken(token); - } catch (ExpiredJwtException e) { - System.err.println(e.getMessage()); - acknowledge(false); - return; - } catch (Throwable ignored) { - System.out.println("Token format not valid"); - acknowledge(false); - return; - } - - final User user = userRepository.findByUsername(username); - if (user == null || jwtTokenUtils.isTokenExpired(token)) { - System.out.println("Token not valid"); - acknowledge(false); - return; - } - - // Here user is authenticated - session.removeMessageHandler(this); - - // Add user-session pair in authorized list - authorizedSetter.accept(user, session); - - // update client to acknowledge authentication - acknowledge(true); - } - - private void acknowledge(boolean success) { - try { - session.getBasicRemote() - .sendText(gson.toJson(Map.of("authenticated", success))); - } catch (IOException e) { - e.printStackTrace(); - } - } - }; - } -} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketEndpoint.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketEndpoint.java index 600bdf4..44c754b 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketEndpoint.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketEndpoint.java @@ -2,51 +2,43 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.socket; import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonConfig; +import ch.usi.inf.sa4.sanmarinoes.smarthut.config.JWTTokenUtils; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.gson.Gson; + import java.io.IOException; import java.util.*; import javax.websocket.*; + +import com.google.gson.JsonObject; +import io.jsonwebtoken.ExpiredJwtException; +import org.hibernate.annotations.common.reflection.XProperty; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -/** Endpoint of socket at URL /sensor-socket used to update the client with sensor information */ +/** + * Endpoint of socket at URL /sensor-socket used to update the client with sensor information + */ @Component public class SensorSocketEndpoint extends Endpoint { private Gson gson = GsonConfig.gson(); - private AuthenticationMessageListener authenticationMessageListener; + private UserRepository userRepository; - private Set unauthorizedClients = Collections.synchronizedSet(new HashSet<>()); + private JWTTokenUtils jwtTokenUtils; private Multimap authorizedClients = Multimaps.synchronizedMultimap(HashMultimap.create()); @Autowired - public SensorSocketEndpoint(AuthenticationMessageListener authenticationMessageListener) { - this.authenticationMessageListener = authenticationMessageListener; - } - - /** - * Returns a synchronized set of socket sessions not yet authorized with a token - * - * @return a synchronized set of socket sessions not yet authorized with a token - */ - public Set getUnauthorizedClients() { - return unauthorizedClients; - } - - /** - * Returns a synchronized User to Session multimap with authorized sessions - * - * @return a synchronized User to Session multimap with authorized sessions - */ - public Multimap getAuthorizedClients() { - return authorizedClients; + public SensorSocketEndpoint(UserRepository userRepository, JWTTokenUtils jwtTokenUtils) { + this.jwtTokenUtils = jwtTokenUtils; + this.userRepository = userRepository; } /** @@ -54,8 +46,7 @@ public class SensorSocketEndpoint extends Endpoint { * returns the number of successful transfers * * @param message the message to send - * @param u the user to which to send the message - * @return number of successful transfer + * @param u the user to which to send the message */ public void broadcast(Object message, User u) { final HashSet sessions = new HashSet<>(authorizedClients.get(u)); @@ -76,17 +67,37 @@ public class SensorSocketEndpoint extends Endpoint { * Handles the opening of a socket session with a client * * @param session the newly born session - * @param config endpoint configuration + * @param config endpoint configuration */ @Override public void onOpen(Session session, EndpointConfig config) { - unauthorizedClients.add(session); - session.addMessageHandler( - authenticationMessageListener.newHandler( - session, - (u, s) -> { - unauthorizedClients.remove(s); - authorizedClients.put(u, s); - })); + final List tokenQuery = session.getRequestParameterMap().get("token"); + User u; + if (!tokenQuery.isEmpty() && (u = checkToken(tokenQuery.get(0))) != null) { + authorizedClients.put(u, session); + } else { + try { + session.close(); + } catch (IOException ignored) { + } + } + } + + private User checkToken(String protocolString) { + String username; + + try { + username = jwtTokenUtils.getUsernameFromToken(protocolString); + } catch (Throwable ignored) { + System.out.println("Token format not valid"); + return null; + } + + final User user = userRepository.findByUsername(username); + if (user != null && !jwtTokenUtils.isTokenExpired(protocolString)) { + return user; + } else { + return null; + } } }