package com.devicehive.websockets.handlers; /* * #%L * DeviceHive Frontend Logic * %% * Copyright (C) 2016 DataArt * %% * 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. * #L% */ import com.devicehive.auth.HiveAuthentication; import com.devicehive.auth.HivePrincipal; import com.devicehive.configuration.Constants; import com.devicehive.model.enums.UserStatus; import com.devicehive.security.jwt.JwtPayload; import com.devicehive.security.jwt.TokenType; import com.devicehive.service.UserService; import com.devicehive.service.security.jwt.JwtClientService; import com.devicehive.service.time.TimestampService; import com.devicehive.vo.ApiInfoVO; import com.devicehive.vo.UserVO; import com.devicehive.websockets.HiveWebsocketSessionState; import com.devicehive.websockets.WebSocketAuthenticationManager; import com.devicehive.websockets.converters.WebSocketResponse; import com.google.gson.JsonObject; import io.jsonwebtoken.MalformedJwtException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.socket.WebSocketSession; import static com.devicehive.json.strategies.JsonPolicyDef.Policy.WEBSOCKET_SERVER_INFO; @Component public class CommonHandlers { private static final Logger logger = LoggerFactory.getLogger(CommonHandlers.class); @Autowired private WebSocketAuthenticationManager authenticationManager; @Autowired private JwtClientService tokenService; @Autowired private UserService userService; @Autowired private TimestampService timestampService; @PreAuthorize("permitAll") public WebSocketResponse processServerInfo(WebSocketSession session) { logger.debug("server/info action started. Session " + session.getId()); ApiInfoVO apiInfo = new ApiInfoVO(); apiInfo.setApiVersion(Constants.class.getPackage().getImplementationVersion()); //TODO: Replace with timestamp service apiInfo.setServerTimestamp(timestampService.getDate()); WebSocketResponse response = new WebSocketResponse(); response.addValue("info", apiInfo, WEBSOCKET_SERVER_INFO); logger.debug("server/info action completed. Session {}", session.getId()); return response; } //TODO - replace with jwt authentication @PreAuthorize("permitAll") public WebSocketResponse processAuthenticate(JsonObject request, WebSocketSession session) { String jwtToken = null; if (request.get("token") != null) { jwtToken = request.get("token").getAsString(); } HiveWebsocketSessionState state = (HiveWebsocketSessionState) session.getAttributes().get(HiveWebsocketSessionState.KEY); HiveAuthentication.HiveAuthDetails details = authenticationManager.getDetails(session); HiveAuthentication authentication = authenticationManager.authenticateJWT(jwtToken, details); HivePrincipal principal = (HivePrincipal) authentication.getPrincipal(); authentication.setHivePrincipal(principal); session.getAttributes().put(WebSocketAuthenticationManager.SESSION_ATTR_AUTHENTICATION, authentication); SecurityContextHolder.getContext().setAuthentication(authentication); state.setHivePrincipal(principal); return new WebSocketResponse(); } @PreAuthorize("permitAll") public WebSocketResponse processRefresh(JsonObject request, WebSocketSession session) { String refreshToken = null; if (request.get("refreshToken") != null) { refreshToken = request.get("refreshToken").getAsString(); } JwtPayload payload; try { payload = tokenService.getPayload(refreshToken); } catch (Exception e) { logger.error(e.getMessage(), e); throw new BadCredentialsException(e.getMessage()); } UserVO user = userService.findById(payload.getUserId()); if (user == null) { String msg = "JwtToken: User not found"; logger.warn(msg); throw new BadCredentialsException(msg); } if (!user.getStatus().equals(UserStatus.ACTIVE)) { String msg = "JwtToken: User is not active"; logger.warn(msg); throw new BadCredentialsException(msg); } if (!payload.getTokenType().equals(TokenType.REFRESH)) { String msg = "JwtToken: refresh token is not valid"; logger.warn(msg); throw new BadCredentialsException(msg); } if (payload.getExpiration().before(timestampService.getDate())) { String msg = "JwtToken: refresh token has expired"; logger.warn(msg); throw new BadCredentialsException(msg); } WebSocketResponse response = new WebSocketResponse(); response.addValue("accessToken", tokenService.generateJwtAccessToken(payload)); return response; } }