diff --git a/fda-authentication-service/Dockerfile b/fda-authentication-service/Dockerfile
index 8315953c3840d95a458306dea64c52a0bdfca7fa..9af6f05c5a09e4e3533781afe60d396844a2a4fc 100644
--- a/fda-authentication-service/Dockerfile
+++ b/fda-authentication-service/Dockerfile
@@ -1,24 +1,6 @@
 ###### FIRST STAGE ######
-FROM maven:slim as build
-MAINTAINER Martin Weise <martin.weise@tuwien.ac.at>
-
-WORKDIR /app
-
-COPY ./rabbitmq-event-listener/pom.xml ./pom.xml
-
-RUN mvn -fn -B dependency:go-offline > /dev/null
-
-COPY ./rabbitmq-event-listener ./
-
-# Make sure it compiles
-RUN mvn -q clean package -DskipTests > /dev/null
-
-RUN mv ./target/rabbitmq-event-listener-*.jar ./target/rabbitmq-event-listener.jar
-
-###### SECOND STAGE ######
 FROM keycloak/keycloak:21.0 as config
-
-COPY --from=build /app/target/rabbitmq-event-listener.jar /opt/keycloak/providers/rabbitmq-event-listener.jar
+MAINTAINER Martin Weise <martin.weise@tuwien.ac.at>
 
 # Enable health and metrics support
 ENV KC_HEALTH_ENABLED=true
@@ -34,7 +16,7 @@ WORKDIR /opt/keycloak
 RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
 RUN /opt/keycloak/bin/kc.sh build
 
-###### THIRD STAGE ######
+###### SECOND STAGE ######
 FROM redhat/ubi9-minimal as binary
 
 RUN microdnf update -y && microdnf install -y curl-minimal libcurl-minimal
@@ -45,7 +27,6 @@ FROM keycloak/keycloak:21.0 as runtime
 COPY --from=config /opt/keycloak/ /opt/keycloak/
 COPY --from=binary /usr/lib64 /usr/lib64
 COPY --from=binary /usr/bin/curl /usr/bin/curl
-COPY --from=build /app/target/rabbitmq-event-listener.jar /opt/keycloak/providers/rabbitmq-event-listener.jar
 
 USER root
 
diff --git a/fda-authentication-service/dbrepo-realm.json b/fda-authentication-service/dbrepo-realm.json
index 82c2595fb2dfecadbc1dcfb0b25f20367f408b4d..37c61f0a609bb5d179f24b67008cddad6e3c3a0f 100644
--- a/fda-authentication-service/dbrepo-realm.json
+++ b/fda-authentication-service/dbrepo-realm.json
@@ -1589,7 +1589,7 @@
   },
   "smtpServer" : { },
   "eventsEnabled" : false,
-  "eventsListeners" : [ "rabbitmq-event-listener", "jboss-logging" ],
+  "eventsListeners" : [ "jboss-logging" ],
   "enabledEventTypes" : [ "SEND_RESET_PASSWORD", "UPDATE_CONSENT_ERROR", "GRANT_CONSENT", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REVOKE_GRANT", "UPDATE_TOTP", "LOGIN_ERROR", "CLIENT_LOGIN", "RESET_PASSWORD_ERROR", "IMPERSONATE_ERROR", "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "RESTART_AUTHENTICATION", "IMPERSONATE", "UPDATE_PROFILE_ERROR", "LOGIN", "OAUTH2_DEVICE_VERIFY_USER_CODE", "UPDATE_PASSWORD_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "TOKEN_EXCHANGE", "AUTHREQID_TO_TOKEN", "LOGOUT", "REGISTER", "DELETE_ACCOUNT_ERROR", "CLIENT_REGISTER", "IDENTITY_PROVIDER_LINK_ACCOUNT", "DELETE_ACCOUNT", "UPDATE_PASSWORD", "CLIENT_DELETE", "FEDERATED_IDENTITY_LINK_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "CLIENT_DELETE_ERROR", "VERIFY_EMAIL", "CLIENT_LOGIN_ERROR", "RESTART_AUTHENTICATION_ERROR", "EXECUTE_ACTIONS", "REMOVE_FEDERATED_IDENTITY_ERROR", "TOKEN_EXCHANGE_ERROR", "PERMISSION_TOKEN", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "EXECUTE_ACTION_TOKEN_ERROR", "SEND_VERIFY_EMAIL", "OAUTH2_DEVICE_AUTH", "EXECUTE_ACTIONS_ERROR", "REMOVE_FEDERATED_IDENTITY", "OAUTH2_DEVICE_CODE_TO_TOKEN", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "UPDATE_EMAIL", "REGISTER_ERROR", "REVOKE_GRANT_ERROR", "EXECUTE_ACTION_TOKEN", "LOGOUT_ERROR", "UPDATE_EMAIL_ERROR", "CLIENT_UPDATE_ERROR", "AUTHREQID_TO_TOKEN_ERROR", "UPDATE_PROFILE", "CLIENT_REGISTER_ERROR", "FEDERATED_IDENTITY_LINK", "SEND_IDENTITY_PROVIDER_LINK", "SEND_VERIFY_EMAIL_ERROR", "RESET_PASSWORD", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "OAUTH2_DEVICE_AUTH_ERROR", "UPDATE_CONSENT", "REMOVE_TOTP_ERROR", "VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD_ERROR", "CLIENT_UPDATE", "CUSTOM_REQUIRED_ACTION_ERROR", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "UPDATE_TOTP_ERROR", "CODE_TO_TOKEN", "VERIFY_PROFILE", "GRANT_CONSENT_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" ],
   "adminEventsEnabled" : false,
   "adminEventsDetailsEnabled" : false,
diff --git a/fda-authentication-service/rabbitmq-event-listener/pom.xml b/fda-authentication-service/rabbitmq-event-listener/pom.xml
deleted file mode 100644
index 5a23bb1780159c5ec35530c7728845b9ea15fc82..0000000000000000000000000000000000000000
--- a/fda-authentication-service/rabbitmq-event-listener/pom.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>org.example</groupId>
-    <artifactId>rabbitmq-event-listener</artifactId>
-    <version>1.0-SNAPSHOT</version>
-    <packaging>jar</packaging>
-
-    <name>Keycloak - Custom Event Listener</name>
-    <description>This event listener will notify an admin about new registrations via Email.</description>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
-        <maven.compiler.source>11</maven.compiler.source>
-        <maven.compiler.target>11</maven.compiler.target>
-
-        <!-- https://mvnrepository.com/artifact/org.keycloak/keycloak-parent -->
-        <keycloak.version>21.0.1</keycloak.version>
-        <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
-        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
-        <!-- https://mvnrepository.com/artifact/org.wildfly.plugins/wildfly-maven-plugin -->
-        <maven-wildfly-plugin.version>2.0.2.Final</maven-wildfly-plugin.version>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-server-spi</artifactId>
-            <version>${keycloak.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-server-spi-private</artifactId>
-            <version>${keycloak.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-services</artifactId>
-            <version>${keycloak.version}</version>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>${maven-compiler-plugin.version}</version>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <version>${maven-wildfly-plugin.version}</version>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file
diff --git a/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProvider.java b/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProvider.java
deleted file mode 100644
index c6e2b52a323257d5c89ad81f1a6e1c783b430c7a..0000000000000000000000000000000000000000
--- a/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProvider.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package at.tuwien;
-
-import org.jboss.logging.Logger;
-import org.keycloak.email.DefaultEmailSenderProvider;
-import org.keycloak.email.EmailException;
-import org.keycloak.events.Event;
-import org.keycloak.events.EventListenerProvider;
-import org.keycloak.events.EventType;
-import org.keycloak.events.admin.AdminEvent;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.UserModel;
-
-import java.util.Map;
-
-public class CustomEventListenerProvider implements EventListenerProvider {
-
-    private static final Logger log = Logger.getLogger(CustomEventListenerProvider.class);
-
-    private final KeycloakSession session;
-    private final RealmProvider model;
-
-    public CustomEventListenerProvider(KeycloakSession session) {
-        this.session = session;
-        this.model = session.realms();
-    }
-
-    @Override
-    public void onEvent(Event event) {
-        if (event.getType().equals(EventType.REGISTER)) {
-
-        }
-    }
-
-    @Override
-    public void onEvent(AdminEvent adminEvent, boolean b) {
-        if (adminEvent.getOperationType().equals(OperationType.CREATE) && adminEvent.getResourcePath().startsWith("users/")) {
-            log.infof("=======> Created user!!");
-        } else if (adminEvent.getOperationType().equals(OperationType.ACTION) && adminEvent.getResourcePath().startsWith("users/") && adminEvent.getResourcePath().endsWith("reset-password")) {
-            log.infof("=======> Modified user password!!");
-        }
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    private void createUser(String username) {
-
-    }
-}
\ No newline at end of file
diff --git a/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProviderFactory.java b/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProviderFactory.java
deleted file mode 100644
index 89d9ded5455b8c6e22b7c08f9f1f6fba60198bf7..0000000000000000000000000000000000000000
--- a/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProviderFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package at.tuwien;
-
-import org.keycloak.Config;
-import org.keycloak.events.EventListenerProvider;
-import org.keycloak.events.EventListenerProviderFactory;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-
-public class CustomEventListenerProviderFactory implements EventListenerProviderFactory {
-
-    @Override
-    public EventListenerProvider create(KeycloakSession keycloakSession) {
-        return new CustomEventListenerProvider(keycloakSession);
-    }
-
-    @Override
-    public void init(Config.Scope scope) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getId() {
-        return "rabbitmq-event-listener";
-    }
-}
\ No newline at end of file
diff --git a/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/jboss-deployment-structure.xml b/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/jboss-deployment-structure.xml
deleted file mode 100644
index c0330ba082479a3bd9d0caf86508b5067251ed84..0000000000000000000000000000000000000000
--- a/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/jboss-deployment-structure.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<jboss-deployment-structure>
-    <deployment>
-        <dependencies>
-            <module name="org.keycloak.keycloak-services" />
-        </dependencies>
-    </deployment>
-</jboss-deployment-structure>
\ No newline at end of file
diff --git a/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory b/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory
deleted file mode 100644
index 5dee2484cc921ab377ff100fc9fe266025f26688..0000000000000000000000000000000000000000
--- a/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory
+++ /dev/null
@@ -1 +0,0 @@
-at.tuwien.CustomEventListenerProviderFactory
\ No newline at end of file
diff --git a/fda-ui/api/user/index.js b/fda-ui/api/user/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..ce0317ad3d4566da88394bd2c134f662631f16cf
--- /dev/null
+++ b/fda-ui/api/user/index.js
@@ -0,0 +1,21 @@
+const axios = require('axios/dist/browser/axios.cjs')
+const qs = require('qs')
+const { clientSecret } = require('@/config')
+function authenticate (username, password) {
+  const payload = {
+    client_id: 'dbrepo-client',
+    username,
+    password,
+    grant_type: 'password',
+    client_secret: clientSecret,
+    scope: 'openid'
+  }
+  console.debug('===>', clientSecret)
+  return axios.post('/api/auth/realms/dbrepo/protocol/openid-connect/token', qs.stringify(payload), {
+    headers: { ContentType: 'application/form-data' }
+  })
+}
+
+module.exports = {
+  authenticate
+}
diff --git a/fda-ui/config.js b/fda-ui/config.js
new file mode 100644
index 0000000000000000000000000000000000000000..8e22479f037e05308d518ac8026378441b4720db
--- /dev/null
+++ b/fda-ui/config.js
@@ -0,0 +1,19 @@
+const config = {}
+
+config.api = process.env.API || 'http://localhost:9095'
+config.search = process.env.SEARCH || 'http://localhost:9200'
+config.sandbox = process.env.SANDBOX || false
+config.title = process.env.TITLE || 'Database Repository'
+config.icon = process.env.ICON || '/favicon.ico'
+config.brokerUsername = process.env.BROKER_USERNAME || 'fda'
+config.brokerPassword = process.env.BROKER_PASSWORD || 'fda'
+config.sharedFilesystem = process.env.SHARED_FILESYSTEM || '/tmp'
+config.version = process.env.VERSION || 'latest'
+config.logo = process.env.LOGO || '/logo.png'
+config.mailVerify = process.env.MAIL_VERIFY || false
+config.tokenMax = process.env.TOKEN_MAX || 5
+config.elasticPassword = process.env.ELASTIC_PASSWORD || 'elastic'
+config.elasticPassword = process.env.ELASTIC_PASSWORD || 'elastic'
+config.clientSecret = process.env.CLIENT_SECRET
+
+module.exports = config
diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue
index 5116d0397fb34a6a4150e097496f7a3eac23b0a0..3b310b25aba3d80ca452a9f31c8a3cb94b4a8321 100644
--- a/fda-ui/layouts/default.vue
+++ b/fda-ui/layouts/default.vue
@@ -122,7 +122,7 @@
 </template>
 
 <script>
-import { isDeveloper } from '@/utils'
+import { isDeveloper, jwtToUser } from '@/utils'
 export default {
   name: 'DefaultLayout',
   data () {
@@ -136,7 +136,13 @@ export default {
       loadingUser: true,
       loadingSearch: false,
       loadingDatabases: false,
-      search: null
+      search: null,
+      refreshToken: {
+        client_id: 'dbrepo-client',
+        grant_type: 'refresh_token',
+        client_secret: this.$config.client_secret,
+        refresh_token: null
+      }
     }
   },
   computed: {
@@ -173,6 +179,14 @@ export default {
         headers: { Authorization: `Bearer ${this.token}` }
       }
     },
+    keycloakConfig () {
+      return {
+        headers: {
+          Authorization: `Bearer ${this.token}`,
+          ContentType: 'application/x-www-form-urlencoded'
+        }
+      }
+    },
     silentConfig () {
       return {
         headers: this.config.headers,
@@ -238,6 +252,7 @@ export default {
     },
     logout () {
       this.$store.commit('SET_TOKEN', null)
+      this.$store.commit('SET_REFRESH_TOKEN', null)
       this.$store.commit('SET_USER', null)
       this.$store.commit('SET_ACCESS', null)
       this.$vuetify.theme.dark = false
@@ -250,11 +265,13 @@ export default {
       try {
         this.loadingUser = true
         const res = await this.$axios.get('/api/auth/realms/dbrepo/protocol/openid-connect/userinfo', this.keycloakConfig)
-        this.$store.commit('SET_USER', res.data)
-        console.debug('user information', this.user)
-        this.$vuetify.theme.dark = this.user.theme_dark
+        const user = jwtToUser(res.data)
+        console.debug('user information', user)
+        this.$store.commit('SET_USER', user)
+        this.$vuetify.theme.dark = user.theme_dark
         this.loading = false
       } catch (err) {
+        console.error('Failed to load user', err)
         const { status } = err.response
         if (status === 401) {
           console.error('Token expired', err)
diff --git a/fda-ui/nuxt.config.js b/fda-ui/nuxt.config.js
index 9327472ae752ff3efb05dd23cab75300030936f0..d5ca9c8cae59bc2d3bba419cff396660b21da296 100644
--- a/fda-ui/nuxt.config.js
+++ b/fda-ui/nuxt.config.js
@@ -1,17 +1,14 @@
 import path from 'path'
 import colors from 'vuetify/es5/util/colors'
+import { sandbox, title, icon, brokerUsername, brokerPassword, sharedFilesystem, version, logo, mailVerify, tokenMax, elasticPassword, clientSecret, api, search } from './config'
 
 // pick env vars from .env file or get them passed through docker-compose
 require('dotenv').config()
 
-if (process.env.SANDBOX) {
+if (sandbox) {
   console.info('[FDA] Running in sandbox environment')
 }
 
-const configTitle = process.env.TITLE || 'Database Repository'
-const configIcon = process.env.ICON || '/favicon.ico'
-const sandbox = process.env.SANDBOX || false
-
 export default {
   target: 'server',
   ssr: false,
@@ -25,14 +22,14 @@ export default {
   },
 
   head: {
-    title: configTitle,
+    title,
     meta: [
       { charset: 'utf-8' },
       { name: 'viewport', content: 'width=device-width, initial-scale=1' },
       { hid: 'description', name: 'description', content: '' }
     ],
     link: [
-      { rel: 'icon', type: 'image/x-icon', href: configIcon }
+      { rel: 'icon', type: 'image/x-icon', href: icon }
     ]
   },
 
@@ -74,20 +71,20 @@ export default {
   },
 
   publicRuntimeConfig: {
-    brokerUsername: process.env.BROKER_USERNAME || 'fda',
-    brokerPassword: process.env.BROKER_PASSWORD || 'fda',
+    brokerUsername,
+    brokerPassword,
     sandbox,
-    sharedFilesystem: process.env.SHARED_FILESYSTEM || '/tmp',
-    version: process.env.VERSION || 'latest',
-    logo: process.env.LOGO || '/logo.png',
-    mailVerify: process.env.MAIL_VERIFY || false,
-    tokenMax: process.env.TOKEN_MAX || 5,
-    elasticPassword: process.env.ELASTIC_PASSWORD || 'elastic',
-    client_secret: process.env.CLIENT_SECRET
+    sharedFilesystem,
+    version,
+    logo,
+    mailVerify,
+    tokenMax,
+    elasticPassword,
+    clientSecret
   },
 
   proxy: {
-    '/api': process.env.API || 'http://localhost:9095',
+    '/api': api,
     '/pid': {
       target: process.env.API + '/api' || 'http://localhost:9095/api',
       changeOrigin: true,
@@ -96,7 +93,7 @@ export default {
       }
     },
     '/retrieve': {
-      target: process.env.SEARCH || 'http://localhost:9200',
+      target: search,
       changeOrigin: true,
       pathRewrite: {
         '^/retrieve': ''
diff --git a/fda-ui/package.json b/fda-ui/package.json
index e0e1c96189fd7d7bf0604df48d5fa0f11324266e..e80cb0ce28d45fa035bf1e7fd21b771b2fb2851a 100644
--- a/fda-ui/package.json
+++ b/fda-ui/package.json
@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "scripts": {
-    "dev": "export NODE_TLS_REJECT_UNAUTHORIZED=0 && nuxt --env.NODE_TLS_REJECT_UNAUTHORIZED=0 --port 3001",
+    "dev": "nuxt --port 3001",
     "docker": "nuxt > /dev/null",
     "build": "nuxt build",
     "start": "nuxt start",
@@ -31,6 +31,7 @@
     "core-js": "^3.6.5",
     "date-fns": "^2.16.1",
     "date-fns-tz": "^1.3.6",
+    "dotenv": "^16.0.3",
     "eslint": "^7.27.0",
     "express": "^4.17.1",
     "is-docker": "^2.2.1",
diff --git a/fda-ui/pages/login.vue b/fda-ui/pages/login.vue
index 5d61dd88f1a870cc102ca627c9261ffe32f84c72..434c091a86c2bd71d5fe1364a7f609f440dfdbb4 100644
--- a/fda-ui/pages/login.vue
+++ b/fda-ui/pages/login.vue
@@ -14,7 +14,7 @@
           <v-row dense>
             <v-col sm="6">
               <v-text-field
-                v-model="loginAccount.username"
+                v-model="username"
                 autocomplete="off"
                 autofocus
                 required
@@ -26,7 +26,7 @@
           <v-row dense>
             <v-col sm="6">
               <v-text-field
-                v-model="loginAccount.password"
+                v-model="password"
                 autocomplete="off"
                 type="password"
                 required
@@ -56,22 +56,15 @@
 </template>
 
 <script>
-import VueJwtDecode from 'vue-jwt-decode'
-import qs from 'qs'
+import { authenticate } from '@/api/user'
 export default {
   data () {
     return {
       loading: false,
       error: false, // XXX: `error` is never changed
       valid: false,
-      loginAccount: {
-        client_id: 'dbrepo-client',
-        username: null,
-        password: null,
-        grant_type: 'password',
-        client_secret: this.$config.client_secret,
-        scope: 'openid'
-      }
+      username: null,
+      password: null
     }
   },
   computed: {
@@ -91,11 +84,6 @@ export default {
       return {
         headers: { Authorization: `Bearer ${this.token}` }
       }
-    },
-    keycloakConfig () {
-      return {
-        headers: { ContentType: 'application/x-www-form-urlencoded' }
-      }
     }
   },
   mounted () {
@@ -114,36 +102,38 @@ export default {
     async login () {
       try {
         this.loading = true
-        const res = await this.$axios.post('/api/auth/realms/dbrepo/protocol/openid-connect/token', qs.stringify(this.loginAccount), this.keycloakConfig)
+        const res = await authenticate(this.username, this.password)
         console.debug('login user', res.data)
         // eslint-disable-next-line camelcase
-        const { access_token } = res.data
-        this.$store.commit('SET_TOKEN', access_token)
-        const data = VueJwtDecode.decode(access_token)
-        const user = {
-          id: data.sub,
-          firstname: data.given_name,
-          lastname: data.family_name,
-          username: data.preferred_username,
-          theme_dark: data.theme_dark,
-          email_verified: data.email_verified
-        }
-        this.$store.commit('SET_USER', user)
-        this.$vuetify.theme.dark = false
-        await this.$router.push({ path: this.$route.query.redirect ? this.$route.query.redirect : '/container' })
+        // const { access_token, refresh_token } = res.data
+        // this.$store.commit('SET_TOKEN', access_token)
+        // this.$store.commit('SET_REFRESH_TOKEN', refresh_token)
+        // const data = VueJwtDecode.decode(access_token)
+        // const user = {
+        //   id: data.sub,
+        //   firstname: data.given_name,
+        //   lastname: data.family_name,
+        //   username: data.preferred_username,
+        //   theme_dark: data.theme_dark,
+        //   email_verified: data.email_verified
+        // }
+        // this.$store.commit('SET_USER', user)
+        // this.$vuetify.theme.dark = user?.theme_dark || false
+        // await this.$router.push({ path: this.$route.query.redirect ? this.$route.query.redirect : '/container' })
       } catch (error) {
-        const { status } = error.response
-        if (status === 418) {
-          this.$toast.error('Check your inbox and confirm your e-mail address')
-          console.error('user has not confirmed e-mail', error)
-        } else if (status === 404) {
-          this.$toast.error('Username not found')
-          console.error('user has not confirmed e-mail', error)
-        } else {
-          this.$toast.error('Login not successful')
-          console.error('login user failed', error)
-        }
-        this.loading = false
+        console.error('Failed to login', error)
+        // const { status } = error.response
+        // if (status === 418) {
+        //   this.$toast.error('Check your inbox and confirm your e-mail address')
+        //   console.error('user has not confirmed e-mail', error)
+        // } else if (status === 404) {
+        //   this.$toast.error('Username not found')
+        //   console.error('user has not confirmed e-mail', error)
+        // } else {
+        //   this.$toast.error('Login not successful')
+        //   console.error('login user failed', error)
+        // }
+        // this.loading = false
       }
     },
     signup () {
diff --git a/fda-ui/pages/user/info.vue b/fda-ui/pages/user/info.vue
index c4870864e7966fc4f70dc6aea6d5b140608dc98b..d9d6adc43651dc3c141f8ff182316bd08fef7096 100644
--- a/fda-ui/pages/user/info.vue
+++ b/fda-ui/pages/user/info.vue
@@ -1,5 +1,6 @@
 <template>
   <div v-if="token">
+    <pre>{{ user }}</pre>
     <UserToolbar />
     <v-tabs-items v-model="tab">
       <v-tab-item>
diff --git a/fda-ui/store/index.js b/fda-ui/store/index.js
index 890c896dd56aca203765f500eca2f91102fb2155..d7cd95a022d8731e46b4287d1f36ab461ddbbadb 100644
--- a/fda-ui/store/index.js
+++ b/fda-ui/store/index.js
@@ -1,5 +1,6 @@
 export const state = () => ({
   token: null,
+  refreshToken: null,
   user: null,
   database: null,
   table: null,
@@ -13,6 +14,9 @@ export const mutations = {
   SET_TOKEN (state, token) {
     state.token = token
   },
+  SET_REFRESH_TOKEN (state, refreshToken) {
+    state.refreshToken = refreshToken
+  },
   SET_USER (state, user) {
     if (user != null && user.token) {
       delete user.token
diff --git a/fda-ui/utils/index.js b/fda-ui/utils/index.js
index 2cb3310639179d677ae038562ba7be92a03504c8..29c0e8385d09c11e92592062266d66069ef9b059 100644
--- a/fda-ui/utils/index.js
+++ b/fda-ui/utils/index.js
@@ -1,4 +1,5 @@
 const { format } = require('date-fns')
+const VueJwtDecode = require('vue-jwt-decode')
 
 function notEmpty (str) {
   return typeof str === 'string' && str.trim().length > 0
@@ -152,6 +153,29 @@ function formatTimestampUTC (str) {
   return format(new Date(date), 'yyyy-MM-dd HH:mm:ss')
 }
 
+function jwtToUser (jwt) {
+  // eslint-disable-next-line camelcase
+  const { access_token } = jwt
+  const data = VueJwtDecode.decode(access_token)
+  return {
+    id: data.sub,
+    firstname: data.given_name,
+    lastname: data.family_name,
+    username: data.preferred_username,
+    theme_dark: data?.theme_dark,
+    orcid: data?.orcid,
+    titles_before: data?.titles_before,
+    titles_after: data?.titles_after,
+    email_verified: data.email_verified
+  }
+}
+
+function isTokenExpired (accessToken) {
+  const data = VueJwtDecode.decode(accessToken)
+  const exp = new Date(data.exp)
+  return exp <= new Date()
+}
+
 module.exports = {
   notEmpty,
   formatTimestamp,
@@ -166,5 +190,7 @@ module.exports = {
   formatCreators,
   isDeveloper,
   isResearcher,
-  isDataSteward
+  isDataSteward,
+  jwtToUser,
+  isTokenExpired
 }
diff --git a/fda-ui/yarn.lock b/fda-ui/yarn.lock
index c13f79ce87b2b72bc9c6e59bcb8157db87582c41..3ca5ba3bbdd1ae9baf45f3e80b9d117037d8068c 100644
--- a/fda-ui/yarn.lock
+++ b/fda-ui/yarn.lock
@@ -4744,6 +4744,11 @@ dot-prop@^5.2.0:
   dependencies:
     is-obj "^2.0.0"
 
+dotenv@^16.0.3:
+  version "16.0.3"
+  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07"
+  integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==
+
 dotenv@^8.1.0:
   version "8.6.0"
   resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
@@ -5774,6 +5779,11 @@ fs.realpath@^1.0.0:
   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
   integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
 
+fs@^0.0.1-security:
+  version "0.0.1-security"
+  resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4"
+  integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==
+
 fsevents@^1.2.7:
   version "1.2.13"
   resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"