From d5a8f417ac0ae692dc7f27c0a24509fa9ab92314 Mon Sep 17 00:00:00 2001 From: kravchenkodhealth <106426895+kravchenkodhealth@users.noreply.github.com> Date: Wed, 21 Dec 2022 13:46:04 +0200 Subject: [PATCH] [@dhealthdapps/backend] feat(widgets): added challenge cookie --- .../src/common/gateways/BaseGateway.ts | 39 ++++++++++++++----- .../src/common/routes/AuthController.ts | 21 +++++++++- runtime/dapp-frontend-vue/src/App.ts | 2 +- .../src/views/LoginScreen/LoginScreen.ts | 14 +++---- 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/runtime/backend/src/common/gateways/BaseGateway.ts b/runtime/backend/src/common/gateways/BaseGateway.ts index 562ddf42..10a613df 100644 --- a/runtime/backend/src/common/gateways/BaseGateway.ts +++ b/runtime/backend/src/common/gateways/BaseGateway.ts @@ -15,16 +15,19 @@ import { OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, + MessageBody, } from "@nestjs/websockets"; import { Server } from "https"; +import { JwtService } from "@nestjs/jwt"; // internal dependencies import dappConfigLoader from "../../../config/dapp"; +import { AuthService } from "../services"; const dappConfig = dappConfigLoader(); @WebSocketGateway(80, { - path: `${dappConfig.dappName}`, + path: "/ws", cors: { origin: process.env.FRONTEND_URL, }, @@ -32,7 +35,7 @@ const dappConfig = dappConfigLoader(); export abstract class BaseGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect { - constructor() { + constructor(private readonly authService: AuthService) { this.clients = []; } @@ -41,20 +44,36 @@ export abstract class BaseGateway protected clients: string[]; - handleConnection(server: any) { - console.log("BASEGATEWAY: Client connected"); - this.clients.push(server.client.id); - console.log({ clients: this.clients }); + handleConnection(ws: any, req: any) { + // const challenge = this.getChallengeFromUrl(client); + // this.clients.push(challenge); + console.log("client connected", this.authService.getCookie()); + const str = req.headers.cookie.split("=")[1]; + console.log("DECODED ???????????", decodeURIComponent(str.split(".")[1])); + + ws.cookie = req.headers.cookie; + + // console.log("cookie: ", req.headers); } - handleDisconnect(server: any) { + handleDisconnect(ws: any) { + // const challenge = this.getChallengeFromUrl(client); console.log("BASEGATEWAY: Client disconnected"); - this.clients = this.clients.filter( - (clientId) => clientId !== server.client.id, - ); + console.log("disconnect: ", ws.cookie); + + // this.clients = this.clients.filter( + // (clientId) => clientId !== server.client.id, + // ); } afterInit(server: Server) { console.log("GATEWAY INITIALIZED"); } + + protected getChallengeFromUrl(client: any) { + const { url } = client; + const challenge = url.split("=")[1]; + + return challenge; + } } diff --git a/runtime/backend/src/common/routes/AuthController.ts b/runtime/backend/src/common/routes/AuthController.ts index 090e8186..ef0c6ab2 100644 --- a/runtime/backend/src/common/routes/AuthController.ts +++ b/runtime/backend/src/common/routes/AuthController.ts @@ -150,6 +150,12 @@ export class AuthController { private readonly accountSessionsService: AccountSessionsService, ) {} + /** + * This property stores authentication challenge + * generated when created in getAuthCode() + * **/ + protected challenge: string; + /** * This method generates an *authentication cookie* depending * on the runtime configuration (dApp), i.e. the cookie will @@ -182,10 +188,23 @@ export class AuthController { }) @ApiExtraModels(AuthChallengeDTO) @ApiOkResponse(HTTPResponses.AuthChallengeResponseSchema) - protected async getAuthCode(): Promise { + protected async getAuthCode( + @NestResponse({ passthrough: true }) response: Response, + ): Promise { // generates a *random* authentication challenge const authChallenge = this.authService.getChallenge(); + // generates cookie configuration (depends on dApp) + const authCookie = this.authService.getCookie(); + + // set auth challenge. + // @link https://www.npmjs.com/package/cookie + response.cookie("challenge", authChallenge, { + httpOnly: true, + domain: authCookie.domain, + signed: true, + }); + // serves the authentication challenge return { challenge: authChallenge } as AuthChallengeDTO; } diff --git a/runtime/dapp-frontend-vue/src/App.ts b/runtime/dapp-frontend-vue/src/App.ts index aa9bcba4..f2b38b1b 100644 --- a/runtime/dapp-frontend-vue/src/App.ts +++ b/runtime/dapp-frontend-vue/src/App.ts @@ -188,7 +188,7 @@ export default class App extends MetaView { * @returns void * @access public */ - beforeDestoyed() { + beforeDestroy() { this.$root.$off("modal", this.showModal); this.$root.$off("modal-close", this.hideModal); } diff --git a/runtime/dapp-frontend-vue/src/views/LoginScreen/LoginScreen.ts b/runtime/dapp-frontend-vue/src/views/LoginScreen/LoginScreen.ts index a97e7d8c..842653b9 100644 --- a/runtime/dapp-frontend-vue/src/views/LoginScreen/LoginScreen.ts +++ b/runtime/dapp-frontend-vue/src/views/LoginScreen/LoginScreen.ts @@ -25,7 +25,7 @@ import { QRCode, QRCodeGenerator } from "@dhealth/qr-library"; import { Component } from "vue-property-decorator"; import { mapGetters } from "vuex"; import InlineSvg from "vue-inline-svg"; -import { io } from "socket.io-client"; +import ws from "ws"; // internal dependencies import { MetaView } from "@/views/MetaView"; @@ -64,7 +64,6 @@ export interface TutorialStepItem { id: string; text: string; } - /** * @label PAGES * @class LoginScreen @@ -322,13 +321,12 @@ export default class LoginScreen extends MetaView { public async mounted() { this.qrConfig = this.createLoginQRCode(); - this.wsConnection = new WebSocket("ws://localhost:80/ELEVATE"); + this.wsConnection = new WebSocket("ws://localhost:80/ws"); - // this.wsConnection.on("connect", () => { - // console.log("Successfully connected to the echo websocket server..."); - // }); + this.wsConnection.onopen = function () { + console.log("Successfully connected to the echo websocket server..."); + }; - // // this.wsConnection.send("auth.open", JSON.stringify({ val: "test" })); // this.wsConnection.emit("auth.open", { data: "test msg" }, (res: any) => { // console.log({ res }); // }); @@ -385,6 +383,8 @@ export default class LoginScreen extends MetaView { if (this.globalIntervalTimer) { clearTimeout(this.globalIntervalTimer); } + + this.wsConnection.close(120, this.authChallenge); } /**