diff --git a/src/App.vue b/src/App.vue
index 420561b7dd8162a2950310338fd572d9acf45fd4..e293b275eeb1734b9b1b052650c3b7e19088ea7f 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,16 +1,33 @@
 <script setup lang="ts">
 import NavbarTop from "./components/NavbarTop.vue";
-import SidebarLeft from "./components/SidebarLeft.vue";
+import { onBeforeMount } from "vue";
+import { useCookies } from "vue3-cookies";
+import { useAuthStore } from "@/stores/auth";
+import { useRouter } from "vue-router";
+
+const { cookies } = useCookies();
+const store = useAuthStore();
+const router = useRouter();
+
+onBeforeMount(() => {
+  store.setToken(cookies.get("bearer"));
+  router.beforeEach(async (to) => {
+    // make sure the user is authenticated
+    if (
+      !store.authenticated &&
+      // ❗️ Avoid an infinite redirect
+      to.name !== "login"
+    ) {
+      // redirect the user to the login page
+      return { name: "login" };
+    }
+  });
+});
 </script>
 
-<template style="height: 100%">
+<template>
   <NavbarTop />
-  <SidebarLeft />
-  <router-view class="cona"></router-view>
+  <router-view></router-view>
 </template>
 
-<style scoped>
-.cona {
-  min-height: 80vh;
-}
-</style>
+<style scoped></style>
diff --git a/src/assets/images/ls-login.png b/src/assets/images/ls-login.png
new file mode 100644
index 0000000000000000000000000000000000000000..ab72fa293def5199720b4a00bac0d824aad6d26a
Binary files /dev/null and b/src/assets/images/ls-login.png differ
diff --git a/src/assets/logo.svg b/src/assets/logo.svg
deleted file mode 100644
index bc826fed80ad0c846e5ca25978776f555f4a2370..0000000000000000000000000000000000000000
--- a/src/assets/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"  xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
\ No newline at end of file
diff --git a/src/components/NavbarTop.vue b/src/components/NavbarTop.vue
index edf18f4400735c1f171ae6eab84b1bdf42cec32b..07ad562daac5ad49e6bfd6e55335412fae788652 100644
--- a/src/components/NavbarTop.vue
+++ b/src/components/NavbarTop.vue
@@ -2,8 +2,15 @@
 import BootstrapIcon from "./BootstrapIcon.vue";
 import { reactive, onBeforeUnmount, onMounted } from "vue";
 import { MiscellaneousService } from "@/client";
+import { useAuthStore } from "@/stores/auth";
+import { useRouter } from "vue-router";
+import { useCookies } from "vue3-cookies";
 
-const api_connection = reactive({ connected: false, timer: null });
+const router = useRouter();
+const store = useAuthStore();
+const { cookies } = useCookies();
+
+const api_connection = reactive({ connected: true, timer: null });
 let timer: ReturnType<typeof setInterval> | undefined = undefined;
 function checkApiHealth() {
   MiscellaneousService.miscellaneousHealthCheck()
@@ -15,6 +22,12 @@ function checkApiHealth() {
     });
 }
 
+function logout() {
+  store.logout();
+  cookies.remove("bearer");
+  router.push({ name: "login" });
+}
+
 onMounted(() => {
   checkApiHealth();
   timer = setInterval(checkApiHealth, 10000);
@@ -36,7 +49,10 @@ onBeforeUnmount(() => {
       >
         Backend not reachable
       </span>
-      <div class="dropdown d-flex me-3">
+      <div
+        class="dropdown d-flex me-3"
+        v-if="store.authenticated && store.user != null"
+      >
         <a
           href="#"
           class="d-flex align-items-center text-white text-decoration-none dropdown-toggle-split"
@@ -44,7 +60,7 @@ onBeforeUnmount(() => {
           data-bs-toggle="dropdown"
           aria-expanded="false"
         >
-          <strong class="me-2">Bilbo Baggins</strong>
+          <strong class="me-2">{{ store.user.display_name }}</strong>
           <bootstrap-icon
             icon="person-circle"
             fill="white"
@@ -56,15 +72,18 @@ onBeforeUnmount(() => {
           class="dropdown-menu dropdown-menu-dark text-small shadow"
           aria-labelledby="dropdownUser1"
         >
-          <li><a class="dropdown-item" href="#">New project...</a></li>
-          <li><a class="dropdown-item" href="#">Settings</a></li>
-          <li><a class="dropdown-item" href="#">Profile</a></li>
           <li><hr class="dropdown-divider" /></li>
-          <li><a class="dropdown-item" href="#">Sign out</a></li>
+          <li>
+            <a class="dropdown-item pseudo-link" @click="logout">Sign out</a>
+          </li>
         </ul>
       </div>
     </div>
   </nav>
 </template>
 
-<style scoped></style>
+<style scoped>
+.pseudo-link {
+  cursor: pointer;
+}
+</style>
diff --git a/src/components/SidebarLeft.vue b/src/components/SidebarLeft.vue
index a5d18665f20910f3f14d1fa6bb6ec3d756b064e8..677c417e8f4b40c0bbcb034854ab259e15c2560a 100644
--- a/src/components/SidebarLeft.vue
+++ b/src/components/SidebarLeft.vue
@@ -2,32 +2,28 @@
 
 <template>
   <div
-    class="d-flex flex-column flex-shrink-0 p-3 text-white bg-dark"
-    style="width: 200px"
+    class="d-flex flex-column flex-shrink-0 p-3 text-white bg-dark position-fixed top-50 start-0 translate-middle-y"
+    style="width: 200px; min-height: 80vh"
   >
     <ul class="nav nav-pills flex-column mb-auto">
-      <li class="nav-item">
+      <li class="nav-item mb-1">
         <button
-          class="btn btn-toggle align-items-center rounded collapsed text-white"
+          class="btn btn-lg btn-toggle align-items-center rounded collapsed text-white"
           data-bs-toggle="collapse"
-          data-bs-target="#home-collapse"
+          data-bs-target="#os-collapse"
           aria-expanded="true"
         >
           Object Storage
         </button>
-        <div class="collapse show" id="home-collapse">
+        <div class="collapse show fs-5" id="os-collapse">
           <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
             <li>
-              <router-link
-                to="/object-storage/buckets"
-                class="link-light rounded"
+              <router-link :to="{ name: 'buckets' }" class="link-light rounded"
                 >Buckets</router-link
               >
             </li>
             <li>
-              <router-link
-                to="/object-storage/s3-keys"
-                class="link-light rounded"
+              <router-link :to="{ name: 's3_keys' }" class="link-light rounded"
                 >S3 Keys</router-link
               >
             </li>
@@ -38,4 +34,5 @@
   </div>
 </template>
 
-<style scoped></style>
+<style scoped>
+</style>
diff --git a/src/router/index.ts b/src/router/index.ts
index 3cc545efae8506530b96dd66ec15e72b0238fc60..6034817887ef91bc8e17408158b5e7832621f30e 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -1,21 +1,35 @@
 import { createRouter, createWebHistory } from "vue-router";
 import BucketsView from "../views/BucketsView.vue";
+import DashboardView from "../views/DashboardView.vue";
+import LoginView from "../views/LoginView.vue";
 
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
   routes: [
     {
-      path: "/object-storage/buckets",
-      name: "buckets",
-      component: BucketsView,
+      path: "/dashboard",
+      name: "dashboard",
+      component: DashboardView,
+      children: [
+        {
+          path: "object-storage/buckets",
+          name: "buckets",
+          component: BucketsView,
+        },
+        {
+          path: "object-storage/s3-keys",
+          name: "s3_keys",
+          // route level code-splitting
+          // this generates a separate chunk (About.[hash].js) for this route
+          // which is lazy-loaded when the route is visited.
+          component: () => import("../views/S3KeysView.vue"),
+        },
+      ],
     },
     {
-      path: "/object-storage/s3-keys",
-      name: "about",
-      // route level code-splitting
-      // this generates a separate chunk (About.[hash].js) for this route
-      // which is lazy-loaded when the route is visited.
-      component: () => import("../views/S3KeysView.vue"),
+      path: "/login",
+      name: "login",
+      component: LoginView,
     },
     {
       path: "/",
diff --git a/src/stores/auth.ts b/src/stores/auth.ts
new file mode 100644
index 0000000000000000000000000000000000000000..93dd60eaa64a3db0b5f9e0852e33d0f16ece69d8
--- /dev/null
+++ b/src/stores/auth.ts
@@ -0,0 +1,45 @@
+import { defineStore } from "pinia";
+import type { User } from "@/client";
+import { UserService } from "@/client";
+import { OpenAPI } from "@/client";
+
+export type RootState = {
+  token: string | null;
+  user: User | null;
+};
+
+export const useAuthStore = defineStore({
+  id: "auth",
+  state: () =>
+    ({
+      token: null,
+      user: null,
+    } as RootState),
+  getters: {
+    authenticated: (state) => state.token != null,
+  },
+  actions: {
+    setToken(token: string | null) {
+      if (token != null) {
+        OpenAPI.TOKEN = token;
+        this.token = token;
+        UserService.userGetLoggedInUser()
+          .then((user) => {
+            this.user = user;
+          })
+          .catch(() => {
+            this.token = null;
+          });
+      } else {
+        this.token = null;
+        this.user = null;
+      }
+    },
+    updateUser() {
+      this.setToken(this.token);
+    },
+    logout() {
+      this.setToken(null);
+    },
+  },
+});
diff --git a/src/views/BucketsView.vue b/src/views/BucketsView.vue
index 94874bbaa4e3c1028874d2e9dc2796b47f975f6e..3635de2549d203e645aad1cd7c96ccf7140fc3bf 100644
--- a/src/views/BucketsView.vue
+++ b/src/views/BucketsView.vue
@@ -1,25 +1,7 @@
-<script setup lang="ts">
-import { onMounted, reactive } from "vue";
-import { useCookies } from "vue3-cookies";
-
-const { cookies } = useCookies();
-const my_cookie = reactive({
-  val: "defaults",
-});
-
-onMounted(() => {
-  if (cookies.isKey("bearer")) {
-    my_cookie.val = cookies.get("bearer");
-  }
-});
-</script>
+<script setup lang="ts"></script>
 
 <template>
   <main>
-    <p v-if="my_cookie.val !== 'defaults'">
-      Cookie Present: {{ my_cookie.val }}
-    </p>
-    <p v-else>No Cookie set</p>
     <div>This the is the Buckets Page</div>
   </main>
 </template>
diff --git a/src/views/DashboardView.vue b/src/views/DashboardView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ed97b6c31c9465a513929051ac1bdee5aca896a4
--- /dev/null
+++ b/src/views/DashboardView.vue
@@ -0,0 +1,10 @@
+<script setup lang="ts">
+import SidebarLeft from "../components/SidebarLeft.vue";
+</script>
+
+<template>
+  <SidebarLeft />
+  <router-view></router-view>
+</template>
+
+<style scoped></style>
diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5de83ebb2da5e07d155dcba45ab06219d5cc5c0d
--- /dev/null
+++ b/src/views/LoginView.vue
@@ -0,0 +1,34 @@
+<script setup lang="ts">
+import { onBeforeMount } from "vue";
+import { useAuthStore } from "@/stores/auth";
+import { useRouter } from "vue-router";
+import { OpenAPI } from "@/client";
+
+const router = useRouter();
+
+const store = useAuthStore();
+
+onBeforeMount(() => {
+  if (store.authenticated) {
+    // If user is authenticated redirect him to the dashboard
+    router.push({ name: "buckets" });
+  }
+});
+</script>
+
+<template>
+  <div
+    class="card text-center bg-dark ms-md-auto position-absolute top-50 left-50 translate-middle"
+  >
+    <div class="card-header text-dark bg-light">LoginView</div>
+    <div class="card-body p-5">
+      <h5 class="card-title">Login</h5>
+      <p class="card-text">Login to this service with LifeScience</p>
+      <a :href="OpenAPI.BASE + '/auth/login'" class="m-2">
+        <img src="/src/assets/images/ls-login.png" alt="[LS Login]" />
+      </a>
+    </div>
+  </div>
+</template>
+
+<style scoped></style>