From 5147b73597c7f973af20caef48807cfc07d0a711 Mon Sep 17 00:00:00 2001
From: xaralis <filip.varecha@fragaria.cz>
Date: Wed, 6 Jan 2021 17:03:30 +0100
Subject: [PATCH] fix: app not realising refresh token has expired

---
 src/App.jsx          | 10 ++++++++--
 src/actions/users.js | 30 +++++++++++++++++++++++++++++-
 src/index.js         | 10 ++++++++++
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/src/App.jsx b/src/App.jsx
index 52e77a4..a8c3e9f 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -11,7 +11,7 @@ import { loadAnnouncements } from "actions/announcements";
 import { loadConfig } from "actions/global-info";
 import { loadPosts } from "actions/posts";
 import { loadProgram } from "actions/program";
-import { loadMe } from "actions/users";
+import { loadMe, refreshAccessToken } from "actions/users";
 import { initializeWSChannel } from "actions/ws";
 import Footer from "components/Footer";
 import Navbar from "components/Navbar";
@@ -39,7 +39,12 @@ if (process.env.REACT_APP_SENTRY_DSN) {
 
 const ReactHint = ReactHintFactory(React);
 
-const onKeycloakEvent = (event) => {
+const onKeycloakEvent = async (event) => {
+  if (event === "onTokenExpired") {
+    console.warn("[auth] access token expired, attempting refresh");
+    refreshAccessToken();
+  }
+
   if (["onAuthRefreshSuccess", "onAuthSuccess"].includes(event)) {
     Sentry.setUser(keycloak.tokenParsed);
 
@@ -154,6 +159,7 @@ const AuthenticatedApp = () => {
         initConfig={keycloakInitConfig}
         LoadingComponent={LoadingComponent}
         onEvent={onKeycloakEvent}
+        autoRefreshToken={false}
       >
         <Suspense fallback={LoadingComponent}>
           <ConfiguredApp />
diff --git a/src/actions/users.js b/src/actions/users.js
index 3bb8fb4..c3a6266 100644
--- a/src/actions/users.js
+++ b/src/actions/users.js
@@ -1,7 +1,10 @@
+import * as Sentry from "@sentry/react";
 import { createAsyncAction, errorResult, successResult } from "pullstate";
 
 import { fetch } from "api";
-import { AuthStore } from "stores";
+import keycloak from "keycloak";
+import { AuthStore, PostStore } from "stores";
+import { updateWindowPosts } from "utils";
 
 export const loadMe = createAsyncAction(
   /**
@@ -89,3 +92,28 @@ export const inviteToJitsi = createAsyncAction(
     }
   }
 );
+
+export const refreshAccessToken = async () => {
+  try {
+    await keycloak.updateToken(300);
+    console.info("[auth] access token refreshed");
+  } catch (exc) {
+    console.warn(
+      "[auth] could not refresh the access token, refresh token possibly expired, logging out"
+    );
+
+    Sentry.setUser(null);
+
+    AuthStore.update((state) => {
+      state.isAuthenticated = false;
+      state.user = null;
+      state.showJitsiInvitePopup = false;
+      state.jitsiPopupDimissed = false;
+    });
+
+    PostStore.update((state) => {
+      state.filters.showPendingProposals = false;
+      updateWindowPosts(state);
+    });
+  }
+};
diff --git a/src/index.js b/src/index.js
index 63f1337..7565c0e 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,11 +2,21 @@ import React from "react";
 import ReactDOM from "react-dom";
 import ReactModal from "react-modal";
 
+import { refreshAccessToken } from "actions/users";
+
 import App from "./App";
 import * as serviceWorker from "./serviceWorker";
 
 const root = document.getElementById("root");
 
+function handleVisibilityChange() {
+  if (!document.hidden) {
+    refreshAccessToken();
+  }
+}
+
+document.addEventListener("visibilitychange", handleVisibilityChange, false);
+
 ReactDOM.render(
   <React.StrictMode>
     <App />
-- 
GitLab