Exemplo n.º 1
0
 async def _handle_auth(self, ws_client: WebSocketResponse, token: str):
     """Handle authentication with JWT token."""
     token_info = jwt.decode(token,
                             self.mass.web.jwt_key,
                             algorithms=["HS256"])
     if self.mass.config.security.is_token_revoked(token_info):
         raise AuthenticationError("Token is revoked")
     ws_client.authenticated = True
     self.mass.config.security.set_last_login(token_info["client_id"])
     # TODO: store token/app_id on ws_client obj and periodiclaly check if token is expired or revoked
     await self._send_json(ws_client, result="auth", data=token_info)
Exemplo n.º 2
0
    async def _websocket_handler(self, request: web.Request):
        """Handle websocket client."""

        ws_client = WebSocketResponse()
        ws_client.authenticated = False
        await ws_client.prepare(request)
        request.app["clients"].append(ws_client)

        # handle incoming messages
        async for msg in ws_client:
            try:
                if msg.type == WSMsgType.error:
                    LOGGER.warning("ws connection closed with exception %s",
                                   ws_client.exception())
                if msg.type != WSMsgType.text:
                    continue
                if msg.data == "close":
                    await ws_client.close()
                    break
                # regular message
                json_msg = msg.json(loads=ujson.loads)
                if "command" in json_msg and "data" in json_msg:
                    # handle command
                    await self._handle_command(
                        ws_client,
                        json_msg["command"],
                        json_msg["data"],
                        json_msg.get("id"),
                    )
                elif "event" in json_msg:
                    # handle event
                    await self._handle_event(ws_client, json_msg["event"],
                                             json_msg.get("data"))
            except AuthenticationError as exc:  # pylint:disable=broad-except
                # disconnect client on auth errors
                await self._send_json(ws_client, error=str(exc), **json_msg)
                await ws_client.close(message=str(exc).encode())
            except Exception as exc:  # pylint:disable=broad-except
                # log the error only
                await self._send_json(ws_client, error=str(exc), **json_msg)
                LOGGER.error("Error with WS client", exc_info=exc)

        # websocket disconnected
        request.app["clients"].remove(ws_client)
        LOGGER.debug("websocket connection closed: %s", request.remote)

        return ws_client