diff --git a/package-lock.json b/package-lock.json
index b00e266c5d8bf882654b8e90bb2188ae5fe3869b..52e8f82391ad66170f4ffe771040b0cdab18290f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,13 +14,14 @@
         "axios": "^0.26.1",
         "core-js": "^3.8.3",
         "cssom": "^0.5.0",
+        "jwt-decode": "^3.1.2",
         "roboto-fontface": "*",
         "vue": "^3.2.13",
         "vue-router": "^4.0.3",
         "vuelidate": "^0.7.7",
         "vuex": "^4.0.0",
         "vuex-persistedstate": "^4.1.0",
-        "webfontloader": "^1.0.0"
+        "webfontloader": "^1.6.28"
       },
       "devDependencies": {
         "@babel/core": "^7.12.16",
@@ -11057,6 +11058,11 @@
         "graceful-fs": "^4.1.6"
       }
     },
+    "node_modules/jwt-decode": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
+    },
     "node_modules/kind-of": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -24450,6 +24456,11 @@
         "universalify": "^2.0.0"
       }
     },
+    "jwt-decode": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
+    },
     "kind-of": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
diff --git a/package.json b/package.json
index cce55e6cd844586f7c09af08b82704f174640fc8..1a2ddb7600d61ce70a4bf73e48bccf3bfb399e50 100644
--- a/package.json
+++ b/package.json
@@ -15,13 +15,14 @@
     "axios": "^0.26.1",
     "core-js": "^3.8.3",
     "cssom": "^0.5.0",
+    "jwt-decode": "^3.1.2",
     "roboto-fontface": "*",
     "vue": "^3.2.13",
     "vue-router": "^4.0.3",
     "vuelidate": "^0.7.7",
     "vuex": "^4.0.0",
     "vuex-persistedstate": "^4.1.0",
-    "webfontloader": "^1.0.0"
+    "webfontloader": "^1.6.28"
   },
   "devDependencies": {
     "@babel/core": "^7.12.16",
diff --git a/src/assets/defaultUserProfileImage.jpg b/src/assets/defaultUserProfileImage.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..18c8cd70555d36af38f2bf164b0a22740b14cf6b
Binary files /dev/null and b/src/assets/defaultUserProfileImage.jpg differ
diff --git a/src/components/LoginForm.vue b/src/components/LoginForm.vue
index 4bdfe55bb97a36076a5fee4e4e3f0fd711a6502f..a986f45f67e18ee7834405e64a493da89cedc72e 100644
--- a/src/components/LoginForm.vue
+++ b/src/components/LoginForm.vue
@@ -102,6 +102,7 @@
 import useVuelidate from "@vuelidate/core";
 import { required, email, helpers } from "@vuelidate/validators";
 import { doLogin } from "@/utils/apiutil";
+import { parseUserFromToken } from "@/utils/token-utils";
 
 export default {
   name: "LoginForm.vue",
@@ -165,6 +166,10 @@ export default {
       else {
         console.log("Something went wrong");
       }
+
+      let user = parseUserFromToken();
+      let id = user.account_id;
+      this.$router.push("/profile/" + id);
     },
 
     validate() {
diff --git a/src/components/UserProfileComponents/LargeProfileCard.vue b/src/components/UserProfileComponents/LargeProfileCard.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b27bd17390af37ac6aca878e982ee7b1e46e2c83
--- /dev/null
+++ b/src/components/UserProfileComponents/LargeProfileCard.vue
@@ -0,0 +1,144 @@
+<template>
+  <div
+    class="max-w-sm bg-white rounded-lg border border-gray-200 shadow-md dark:bg-gray-800 dark:border-gray-700"
+  >
+    <div v-show="isCurrentUser" class="flex justify-end px-4 pt-4">
+      <button
+        id="dropdownDefault"
+        data-dropdown-toggle="dropdown"
+        @click="dropdown = !dropdown"
+        class="hidden sm:inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-1.5"
+        type="button"
+      >
+        <svg
+          class="w-6 h-6"
+          fill="currentColor"
+          viewBox="0 0 20 20"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"
+          ></path>
+        </svg>
+      </button>
+
+      <div
+        id="dropdown"
+        v-show="dropdown"
+        zindex="2"
+        class="z-10 w-44 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700"
+      >
+        <ul class="py-1" aria-labelledby="dropdownDefault">
+          <li>
+            <router-link
+              to=""
+              class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Mine gjenstander</router-link
+            >
+          </li>
+          <li>
+            <router-link
+              to=""
+              class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Mine grupper
+            </router-link>
+          </li>
+          <li>
+            <router-link
+              to=""
+              class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Leiehistorikk</router-link
+            >
+          </li>
+          <li>
+            <router-link
+              to="/newPassword"
+              class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Endre passord</router-link
+            >
+          </li>
+          <li>
+            <router-link
+              to=""
+              class="block py-2 px-4 text-sm text-red-600 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Slett bruker</router-link
+            >
+          </li>
+        </ul>
+      </div>
+    </div>
+    <div class="flex flex-col items-center pb-10">
+      <img
+        class="mb-3 w-24 h-24 rounded-full shadow-lg"
+        src="../../assets/defaultUserProfileImage.jpg"
+        alt="Profile picture"
+      />
+      <h5 class="mb-1 text-xl font-medium text-gray-900 dark:text-white">
+        {{ user.first_name }} {{ user.last_name }}
+      </h5>
+      <div>
+        <rating-component :rating="renterRating" :ratingType="'Leietaker'" />
+        <rating-component :rating="ownerRating" :ratingType="'Utleier'" />
+      </div>
+
+      <div v-show="!isCurrentUser" class="flex mt-4 space-x-3 lg:mt-6">
+        <a
+          href="#"
+          class="inline-flex items-center py-2 px-4 text-sm font-medium text-center text-gray-900 bg-white rounded-lg border border-gray-300 hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-gray-200 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-700 dark:focus:ring-gray-700"
+          >Ã…pne chat</a
+        >
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import RatingComponent from "@/components/UserProfileComponents/RatingComponent.vue";
+import { parseUserFromToken } from "@/utils/token-utils";
+import { getUser /* getRenterRating, getOwnerRating */ } from "@/utils/apiutil";
+import router from "@/router";
+
+export default {
+  name: "LargeProfileCard",
+  data() {
+    return {
+      user: {},
+      currentUser: {},
+      id: -1,
+      isCurrentUser: false,
+      renterRating: 0, //getRenterRating(this.userID),
+      ownerRating: 0, //getOwnerRating(this.userID),
+      dropdown: false,
+    };
+  },
+  components: {
+    RatingComponent,
+  },
+  methods: {
+    async getUser() {
+      this.currentUser = parseUserFromToken();
+      this.id = router.currentRoute.value.params.id;
+      if (this.id == this.currentUser.account_id) {
+        this.isCurrentUser = true;
+        this.user = this.currentUser;
+        return;
+      }
+      let getuser = await getUser(this.id);
+      this.user = {
+        account_id: getuser.userID,
+        first_name: getuser.firstName,
+        last_name: getuser.lastName,
+      };
+    },
+    getProfilePicture() {
+      /* if (this.user.picture != "") {
+        return this.user.picture;
+      } */
+      return "../assets/defaultUserProfileImage.jpg";
+    },
+  },
+  beforeMount() {
+    this.getUser();
+  },
+};
+</script>
diff --git a/src/components/UserProfileComponents/RatingComponent.vue b/src/components/UserProfileComponents/RatingComponent.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f79ff22085c106a75f32e0b8294c7ef3c02e9801
--- /dev/null
+++ b/src/components/UserProfileComponents/RatingComponent.vue
@@ -0,0 +1,49 @@
+<template>
+  <ul class="flex justify-center">
+    <li>
+      <p class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">
+        {{ ratingType }}:&nbsp;
+      </p>
+    </li>
+    <li v-for="i in 5" :key="i">
+      <svg
+        :class="getFill(i)"
+        fill="currentColor"
+        viewBox="0 0 20 20"
+        xmlns="http://www.w3.org/2000/svg"
+      >
+        <path
+          d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"
+        ></path>
+      </svg>
+    </li>
+    <li>
+      <p class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">
+        {{ compRating }} out of 5
+      </p>
+    </li>
+  </ul>
+</template>
+
+<script>
+export default {
+  name: "RatingComponent",
+  data() {
+    return {
+      compRating: this.rating + 0,
+    };
+  },
+  props: {
+    rating: Number,
+    ratingType: String,
+  },
+  methods: {
+    getFill(i) {
+      if (i <= this.rating) {
+        return "w-5 h-5 text-yellow-400";
+      }
+      return "w-5 h-5 text-gray-300 dark:text-gray-500";
+    },
+  },
+};
+</script>
diff --git a/src/components/UserProfileComponents/UserListItemCard.vue b/src/components/UserProfileComponents/UserListItemCard.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4da140e21610587c8e88953ed9b17572c9bef98a
--- /dev/null
+++ b/src/components/UserProfileComponents/UserListItemCard.vue
@@ -0,0 +1,40 @@
+<template>
+  <div
+    class="select-none cursor-pointer hover:bg-gray-50 flex flex-1 items-center p-4"
+  >
+    <div class="flex flex-col w-10 h-10 justify-center items-center mr-4">
+      <router-link to="">
+        <img alt="profil" :src="getProfilePicture" />
+      </router-link>
+    </div>
+    <div class="flex-1 pl-1">
+      <div class="font-medium dark:text-white">
+        {{ user.first_name }} {{ user.last_name }}
+      </div>
+    </div>
+    <div class="flex flex-row justify-center">
+      <button class="w-10 text-right flex justify-end">Ã…pne chat</button>
+      <button v-if="admin" class="w-10 text-right flex justify-end">
+        Fjern bruker
+      </button>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "UserListItem",
+  props: {
+    user: Object,
+    admin: Boolean,
+  },
+  methods: {
+    getProfilePicture() {
+      if (this.user.picture != "") {
+        return this.user.picture;
+      }
+      return "../assets/defaultUserProfileImage.jpg";
+    },
+  },
+};
+</script>
diff --git a/src/router/index.js b/src/router/index.js
index cf3844a9c1fffdda6bd0fe3375a0057fc7bc7abf..284f32e9039d6c6cdd0cffed21ddf02be8106929 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,3 +1,4 @@
+import store from "@/store";
 import { createRouter, createWebHistory } from "vue-router";
 import HomeView from "../views/HomeView.vue";
 import LoginView from "../views/LoginView.vue";
@@ -5,18 +6,22 @@ import NewPasswordView from "../views/NewPasswordView";
 
 const routes = [
   {
-    path: "/endre", //Endre før push
+    path: "/", //Endre før push
     name: "home",
     component: HomeView,
   },
   {
     path: "/about",
     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(/* webpackChunkName: "about" */ "../views/AboutView.vue"),
+    component: () => import("../views/AboutView.vue"),
+  },
+  {
+    path: "/profile/:id",
+    name: "profile",
+    component: () => import("../views/ProfileView.vue"),
+    beforeEnter: () => {
+      if (store.state.user.token == null) router.push("login");
+    },
   },
   {
     path: "/register",
@@ -28,7 +33,7 @@ const routes = [
       import(/* webpackChunkName: "register" */ "../views/RegisterView.vue"),
   },
   {
-    path: "/",
+    path: "/login",
     name: "login",
     component: LoginView,
   },
diff --git a/src/utils/apiutil.js b/src/utils/apiutil.js
index 16f9020665a454dcae8223a1c59b08bcfc2fc9fd..887d222831d94469e22f88bdef28c13672fb02db 100644
--- a/src/utils/apiutil.js
+++ b/src/utils/apiutil.js
@@ -1,4 +1,5 @@
 import axios from "axios";
+import { tokenHeader } from "./token-utils";
 
 const API_URL = process.env.VUE_APP_BASEURL;
 
@@ -31,3 +32,42 @@ export function registerUser(registerInfo) {
     })
     .catch((err) => console.log(err));
 }
+
+export async function getUser(userid) {
+  return axios
+    .get(API_URL + "users/" + userid + "/profile", {
+      headers: tokenHeader(),
+    })
+    .then((response) => {
+      return response.data;
+    })
+    .catch((error) => {
+      console.error(error);
+    });
+}
+
+export function getRenterRating(userid) {
+  return axios
+    .get(API_URL + "users/" + userid + "", {
+      headers: tokenHeader(),
+    })
+    .then((response) => {
+      return response.data;
+    })
+    .catch((error) => {
+      console.error(error);
+    });
+}
+
+export function getOwnerRating(userid) {
+  return axios
+    .get(API_URL + "users/" + userid + "", {
+      headers: tokenHeader(),
+    })
+    .then((response) => {
+      return response.data;
+    })
+    .catch((error) => {
+      console.error(error);
+    });
+}
diff --git a/src/utils/token-utils.js b/src/utils/token-utils.js
new file mode 100644
index 0000000000000000000000000000000000000000..baf77654f57a548de5a335038ed9fed4628d80e2
--- /dev/null
+++ b/src/utils/token-utils.js
@@ -0,0 +1,12 @@
+import jwt_decode from "jwt-decode";
+import store from "@/store";
+
+export function tokenHeader() {
+  let token = store.state.user.token;
+  return { Authorization: token };
+}
+
+export function parseUserFromToken() {
+  let token = store.state.user.token;
+  return jwt_decode(token);
+}
diff --git a/src/views/ProfileView.vue b/src/views/ProfileView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cfd2cefd902017ad7b867b7cfe447cce5648cf07
--- /dev/null
+++ b/src/views/ProfileView.vue
@@ -0,0 +1,14 @@
+<!-- View for looking at different profile display methods -->
+<template>
+  <large-profile-card :isCurrentUser="true" />
+</template>
+
+<script>
+import LargeProfileCard from "@/components/UserProfileComponents/LargeProfileCard.vue";
+
+export default {
+  components: {
+    LargeProfileCard,
+  },
+};
+</script>
diff --git a/tests/unit/apiutil-user-mock.spec.js b/tests/unit/apiutil-user-mock.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..73612f0f3579f5c04b99d2424a1a57fd62ff31bc
--- /dev/null
+++ b/tests/unit/apiutil-user-mock.spec.js
@@ -0,0 +1,28 @@
+import { getUser } from "@/utils/apiutil";
+import axios from "axios";
+
+jest.mock("axios");
+
+describe("testing mocking of apiutil.js", () => {
+  it("check that existing user returns correctly", async () => {
+    const expectedResponse = {
+      response:
+        "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhY2NvdW50X2lkIjoiNiIsImV4cCI6MTY1MTEzMDU2NywiZmlyc3RfbmFtZSI6IkFsaWRhIiwiZW1haWwiOiJhbGlkYUB0ZXN0Lm5vIn0.Cp3_qfLhA55j5yaa1WPG97LNtvAZssxo0ROP3VIrHVs",
+    };
+    axios.get.mockImplementation(() =>
+      Promise.resolve({ data: expectedResponse })
+    );
+
+    const userResponse = await getUser(1);
+    expect(userResponse).not.toEqual({ response: "User not found in DB" });
+  });
+  it("check that non-existing user returns 404", async () => {
+    const expectedResponse = { response: "User not found in DB" };
+    axios.get.mockImplementation(() =>
+      Promise.resolve({ data: expectedResponse })
+    );
+
+    const userResponse = await getUser(100000);
+    expect(userResponse).toEqual(expectedResponse);
+  });
+});