diff --git a/fda-ui/api/user/index.js b/fda-ui/api/user/index.js
index ce0317ad3d4566da88394bd2c134f662631f16cf..f4bb4590c1c55fff843af8381f484ff624265a35 100644
--- a/fda-ui/api/user/index.js
+++ b/fda-ui/api/user/index.js
@@ -1,7 +1,9 @@
+// eslint-disable-next-line camelcase
+import jwt_decode from 'jwt-decode'
 const axios = require('axios/dist/browser/axios.cjs')
 const qs = require('qs')
-const { clientSecret } = require('@/config')
-function authenticate (username, password) {
+
+export function authenticate (clientSecret, username, password) {
   const payload = {
     client_id: 'dbrepo-client',
     username,
@@ -10,12 +12,44 @@ function authenticate (username, 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
+export function userinfo (clientSecret, token) {
+  return axios.get('/api/auth/realms/dbrepo/protocol/openid-connect/userinfo', {
+    headers: {
+      Authorization: `Bearer ${token}`,
+      ContentType: 'application/form-data'
+    }
+  })
+}
+
+export function refresh (clientSecret, token) {
+  const payload = {
+    client_id: 'dbrepo-client',
+    grant_type: 'refresh_token',
+    client_secret: clientSecret,
+    refresh_token: token
+  }
+  return axios.post('/api/auth/realms/dbrepo/protocol/openid-connect/token', qs.stringify(payload), {
+    headers: { ContentType: 'application/form-data' }
+  })
+}
+
+export function tokenToUser (token) {
+  const data = jwt_decode(token)
+  return {
+    id: data.sub,
+    firstname: data.given_name,
+    lastname: data.family_name,
+    username: data.preferred_username,
+    theme_dark: data.theme_dark,
+    titles_before: data.titles_before,
+    titles_after: data.titles_after,
+    affiliation: data.affiliation,
+    orcid: data.orcid,
+    email_verified: data.email_verified
+  }
 }
diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue
index 3b310b25aba3d80ca452a9f31c8a3cb94b4a8321..35ccd85ca99ad7e19d6f3ee7eb75127aa3b9360e 100644
--- a/fda-ui/layouts/default.vue
+++ b/fda-ui/layouts/default.vue
@@ -122,7 +122,8 @@
 </template>
 
 <script>
-import { isDeveloper, jwtToUser } from '@/utils'
+import { isDeveloper } from '@/utils'
+import { tokenToUser } from '@/api/user'
 export default {
   name: 'DefaultLayout',
   data () {
@@ -136,13 +137,7 @@ export default {
       loadingUser: true,
       loadingSearch: false,
       loadingDatabases: false,
-      search: null,
-      refreshToken: {
-        client_id: 'dbrepo-client',
-        grant_type: 'refresh_token',
-        client_secret: this.$config.client_secret,
-        refresh_token: null
-      }
+      search: null
     }
   },
   computed: {
@@ -179,13 +174,8 @@ export default {
         headers: { Authorization: `Bearer ${this.token}` }
       }
     },
-    keycloakConfig () {
-      return {
-        headers: {
-          Authorization: `Bearer ${this.token}`,
-          ContentType: 'application/x-www-form-urlencoded'
-        }
-      }
+    clientSecret () {
+      return this.$config.clientSecret
     },
     silentConfig () {
       return {
@@ -252,21 +242,19 @@ 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
       this.$router.push('/container')
     },
-    async loadUser () {
+    loadUser () {
       if (!this.token) {
         return
       }
       try {
         this.loadingUser = true
-        const res = await this.$axios.get('/api/auth/realms/dbrepo/protocol/openid-connect/userinfo', this.keycloakConfig)
-        const user = jwtToUser(res.data)
-        console.debug('user information', user)
+        const user = tokenToUser(this.token)
+        console.debug('user', user)
         this.$store.commit('SET_USER', user)
         this.$vuetify.theme.dark = user.theme_dark
         this.loading = false
diff --git a/fda-ui/nuxt.config.js b/fda-ui/nuxt.config.js
index d5ca9c8cae59bc2d3bba419cff396660b21da296..840e02341c795c2e4969bea69c85c66c65d945f9 100644
--- a/fda-ui/nuxt.config.js
+++ b/fda-ui/nuxt.config.js
@@ -2,9 +2,6 @@ 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 (sandbox) {
   console.info('[FDA] Running in sandbox environment')
 }
diff --git a/fda-ui/package.json b/fda-ui/package.json
index e80cb0ce28d45fa035bf1e7fd21b771b2fb2851a..ff23e62ae94a9fff5f6ad2d24cc4092fa5e861d5 100644
--- a/fda-ui/package.json
+++ b/fda-ui/package.json
@@ -36,6 +36,7 @@
     "express": "^4.17.1",
     "is-docker": "^2.2.1",
     "jose": "^4.9.2",
+    "jwt-decode": "^3.1.2",
     "knex": "^0.95.6",
     "lodash": "^4.17.21",
     "moment": "^2.29.1",
diff --git a/fda-ui/pages/login.vue b/fda-ui/pages/login.vue
index 434c091a86c2bd71d5fe1364a7f609f440dfdbb4..93af6d744a4d6f66dbc9c6fc813adf6aa4852d42 100644
--- a/fda-ui/pages/login.vue
+++ b/fda-ui/pages/login.vue
@@ -56,14 +56,14 @@
 </template>
 
 <script>
-import { authenticate } from '@/api/user'
+import { authenticate, tokenToUser } from '@/api/user'
 export default {
   data () {
     return {
       loading: false,
       error: false, // XXX: `error` is never changed
       valid: false,
-      username: null,
+      username: 'mweise',
       password: null
     }
   },
@@ -77,6 +77,9 @@ export default {
     user () {
       return this.$store.state.user
     },
+    clientSecret () {
+      return this.$config.clientSecret
+    },
     config () {
       if (this.token === null) {
         return {}
@@ -102,38 +105,28 @@ export default {
     async login () {
       try {
         this.loading = true
-        const res = await authenticate(this.username, this.password)
+        const res = await authenticate(this.clientSecret, this.username, this.password)
         console.debug('login user', res.data)
-        // eslint-disable-next-line camelcase
-        // 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' })
+        this.$store.commit('SET_TOKEN', res.data.access_token)
+        const user = tokenToUser(this.token)
+        console.debug('user', user)
+        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) {
         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
+        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 d9d6adc43651dc3c141f8ff182316bd08fef7096..d927c7a516ae9f9fa062180baca539c0aadc8ea0 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>{{ model }}</pre>
     <pre>{{ user }}</pre>
     <UserToolbar />
     <v-tabs-items v-model="tab">
@@ -174,15 +175,7 @@ export default {
     }
   },
   mounted () {
-    this.model.id = this.user.id
-    this.model.username = this.user.username
-    this.model.firstname = this.user.firstname
-    this.model.lastname = this.user.lastname
-    this.model.titles_before = this.user.titles_before
-    this.model.titles_after = this.user.titles_after
-    this.model.affiliation = this.user.affiliation
-    this.model.orcid = this.user.orcid
-    this.model.theme_dark = this.user.theme_dark
+    this.model = Object.assign({}, this.user)
   },
   methods: {
     submit () {
diff --git a/fda-ui/yarn.lock b/fda-ui/yarn.lock
index 3ca5ba3bbdd1ae9baf45f3e80b9d117037d8068c..bff2f60529e64d54be07f685b751033d20e69b24 100644
--- a/fda-ui/yarn.lock
+++ b/fda-ui/yarn.lock
@@ -5779,11 +5779,6 @@ 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"
@@ -7631,6 +7626,11 @@ jsonfile@^6.0.1:
   optionalDependencies:
     graceful-fs "^4.1.6"
 
+jwt-decode@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
+  integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
+
 keyv@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"