From cd78877fd9f8288e9a1176ac4814c9a1e1cf0cb4 Mon Sep 17 00:00:00 2001
From: "@mazikiou" <mazikiou@takima.fr>
Date: Thu, 11 Aug 2022 12:00:34 +0200
Subject: [PATCH] feat: detect and disconnect when invalid refresh token

---
 .../keycloakOAuth2DeviceFlowConnection.ts     | 39 +++++++++++++++++++
 .../deadlock-extension/src/extension.ts       |  2 +
 .../src/view/authenticationView.ts            |  7 ++--
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts b/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts
index 39ba2e4c..dd3adef7 100644
--- a/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts
@@ -10,6 +10,11 @@ import {
 import { HttpStatusCode } from '../customTypings/HttpStatusCode';
 import { TokenFetchErrorCode } from '../customTypings/KeycloakAPITypes';
 import { extensionError as err, extensionLog as log } from '../recorder/utils/log';
+import ExtensionStore from './extensionStore';
+import { commands, window } from 'vscode';
+import Controller from './controller';
+import isMissionStarted from './utils/mission.util';
+import { CommandHandler } from './commandHandler';
 
 process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = REJECT_UNAUTHORIZED ? '1' : '0';
 
@@ -204,6 +209,19 @@ export default class KeycloakOAuth2DeviceFlowConnection {
       case TokenFetchErrorCode.invalid_client:
       case TokenFetchErrorCode.invalid_grant:
       case TokenFetchErrorCode.unsupported_grant_type: {
+        if (badRequestResponse.error_description === 'Invalid refresh token') {
+          if (isMissionStarted()) {
+            commands.executeCommand('workbench.action.remote.close');
+          }
+          window
+            .showInformationMessage('Votre session Deadlock a expiré. Veuillez vous reconnecter.', 'Se reconnecter')
+            .then(async (result) => {
+              if (result === 'Se reconnecter' && !(await ExtensionStore.instance.getAccessToken())) {
+                commands.executeCommand(CommandHandler.instance.authenticateCommand.command);
+              }
+            });
+          Controller.instance.disconnect();
+        }
         err(`${badRequestResponse.error!}: ${badRequestResponse.error_description}`);
         throw new Error('createUserAuthentication: ' + errorCode);
       }
@@ -230,6 +248,27 @@ export default class KeycloakOAuth2DeviceFlowConnection {
     this.accessToken = successRequestResponse.access_token ?? '';
     this.refreshToken = successRequestResponse.refresh_token ?? '';
   }
+
+  public async checkConnection(): Promise<boolean> {
+    const token = await ExtensionStore.instance.getAccessToken();
+    if (!token) {
+      return false;
+    }
+    const isValid = await this.tokenIsValid(token);
+    if (isValid) {
+      return true;
+    }
+    const refreshToken = await ExtensionStore.instance.getAccessToken();
+    const tokens = await this.getToken({
+      refreshToken,
+      openLink: () => {
+        // noop
+      },
+    });
+    ExtensionStore.instance.setAccessToken(tokens.accessToken);
+    ExtensionStore.instance.setRefreshToken(tokens.refreshToken);
+    return true;
+  }
 }
 
 /**
diff --git a/deadlock-plugins/deadlock-extension/src/extension.ts b/deadlock-plugins/deadlock-extension/src/extension.ts
index ae730aa1..8d4d6480 100644
--- a/deadlock-plugins/deadlock-extension/src/extension.ts
+++ b/deadlock-plugins/deadlock-extension/src/extension.ts
@@ -6,6 +6,7 @@ import { CommandTreeProvider } from './view/CommandTree';
 import Controller from './core/controller';
 import isMissionStarted from './core/utils/mission.util';
 import AuthenticationView from './view/authenticationView';
+import KeycloakOAuth2DeviceFlowConnection from './core/keycloakOAuth2DeviceFlowConnection';
 
 export async function activate(context: ExtensionContext) {
   new Controller(context);
@@ -32,4 +33,5 @@ export async function activate(context: ExtensionContext) {
     commands.executeCommand('setContext', 'deadlock.inContainer', false);
     window.registerWebviewViewProvider('authentication', AuthenticationView.instance);
   }
+  KeycloakOAuth2DeviceFlowConnection.instance.checkConnection();
 }
diff --git a/deadlock-plugins/deadlock-extension/src/view/authenticationView.ts b/deadlock-plugins/deadlock-extension/src/view/authenticationView.ts
index 86cf126c..04c47868 100644
--- a/deadlock-plugins/deadlock-extension/src/view/authenticationView.ts
+++ b/deadlock-plugins/deadlock-extension/src/view/authenticationView.ts
@@ -70,10 +70,9 @@ export default class AuthenticationView implements WebviewViewProvider {
 
     const js = getUri(webview, ['resources', 'js', 'authenticationView.js']);
 
-    const html = 
-    `<vscode-button onclick="${
-        this._isAlreadyConnected ? 'disconnectUserAction' : 'openAuthenticationPageAction'
-        }()">${this._isAlreadyConnected ? 'Déconnexion de' : 'Connexion à'} Deadlock
+    const html = `<vscode-button onclick="${
+      this._isAlreadyConnected ? 'disconnectUserAction' : 'openAuthenticationPageAction'
+    }()">${this._isAlreadyConnected ? 'Déconnexion de' : 'Connexion à'} Deadlock
       </vscode-button>`;
 
     return `<!DOCTYPE html>
-- 
GitLab