LardinoisJosse
LardinoisJosse

Reputation: 403

How to retreive JSON web token with axios in Vue?

So I am trying to make a CRUD page for my first Vue project, but I keep getting errors and can't quite find a good solution or example that works.

When I post this request via postman:

Postman

I get results from my database as aspected, but when I try to do this from my vue page I can't seem to get it right. I keep getting a 401 unauthorized error, but I think I do have a header with the token in it.

My vue page:

<template>
  <div class="list row">
    <div class="col-md-8">
    </div>
    <div class="col-md-6">
      <h4>Parties List</h4>
      <ul class="list-group">
        <li class="list-group-item"
            :class="{ active: index == currentIndex }"
            v-for="(party, index) in parties"
            :key="index"
            @click="setActiveParty(party, index)"
        >
          {{ party.name }}
        </li>
      </ul>

      <button class="m-3 btn btn-sm btn-danger" @click="removeAllParties">
        Remove All
      </button>
    </div>
    <div class="col-md-6">
      <div v-if="currentParty">
        <h4>Party</h4>
        <div>
          <label><strong>Title:</strong></label> {{ currentParty.name }}
        </div>
        <div>
          <label><strong>Description:</strong></label> {{ currentParty.description }}
        </div>
        <div>
          <label><strong>Is party national:</strong></label> {{ currentParty.ispartynational ? "Yes" : "No" }}
        </div>
        <div>
          <label><strong>partyLeader:</strong></label> {{ currentParty.partyLeader.name}}
        </div>

        <a class="badge badge-warning"
           :href="'/parties/' + currentParty.id"
        >
          Edit
        </a>
      </div>
      <div v-else>
        <br />
        <p>Please click on a Party...</p>
      </div>
    </div>
  </div>
</template>


<script>
import PartyDataService from "@/services/PartyDataService";
export default {
  name: "PartiesList",
  data() {
    return {
      parties: [],
      currentParty: null,
      currentIndex: -1,
      name: ""
    };
  },
  methods: {
    retrieveParties() {
      PartyDataService.getAll()
          .then(response => {
            this.parties = response.data;
            console.log(response.data);

          })
          .catch(e => {
            console.log(e);
          });
    },

    refreshList() {
      this.retrieveParties();
      this.currentParty = null;
      this.currentIndex = -1;
    },

    setActiveParty(party, index) {
      this.currentParty = party;
      this.currentIndex = index;
    },

    removeAllParties() {
      PartyDataService.deleteAll()
          .then(response => {
            console.log(response.data);
            this.refreshList();
          })
          .catch(e => {
            console.log(e);
          });
    },
    searchName() {
      PartyDataService.findByName(this.name)
          .then(response => {
            this.tutorials = response.data;
            console.log(response.data);
          })
          .catch(e => {
            console.log(e);
          });
    }
  },

  mounted() {
    this.retrieveParties();
  }
};

</script>

<style>
.list {
  text-align: left;
  max-width: 750px;
  margin: auto;
}
</style>

My PartyDataService:

import http from "../http-common";

class PartyDataService {
    getAll() {
        return http.get("/parties");

    }

    get(id) {
        return http.get(`/parties/${id}`);
    }

    create(data) {
        return http.post("/parties/", data);
    }

    update(id, data) {
        return http.put(`/parties/${id}`, data);
    }

    delete(id) {
        return http.delete(`/parties/${id}`);
    }

    deleteAll() {
        return http.delete(`/parties`);
    }
    findByName(name){
        return http.get(`/parties/${name}`)
    }
}

export default new PartyDataService();

My Http-common:

import axios from "axios";

export default axios.create({
    baseURL: "http://localhost:8080/",
    headers: {

         "Content-type": "application/json"
    }

});

I tried to do this in the http-common.js file:

import axios from "axios";

export default axios.create({
    baseURL: "http://localhost:8080/",
    headers: {
         Authorization: 'Bearer ' + localStorage.getItem('Authorization'),
         "Content-type": "application/json"
    }

});

But that gave me the same error plus an extra cors error, that I do not have when I don't include that line of code.

I do not know where to put the line of code (that I think will help me solve my problem). Can anyone help me? Thanks in advance!

Upvotes: 0

Views: 2321

Answers (1)

Tom Bombadil
Tom Bombadil

Reputation: 3975

As per the screenshot of the postman request and the code snippets shared, there seems to be a mismatch in the value of Authorization.

In postman its: Bearer: your_auth_token

In axios headers its: Bearer your_auth_token

The colon after Bearer might just be the issue here.

Also, don't set the authorization header directly in axios.create. Instead create an axios instance and use axios interceptors on the request obj and set the auth token there. Because your auth token can expire, and when you refresh your token, axios will not update the new token from local storage. axios.create only runs once when the instance is created. So, it will use the token that was initially added. But, Axios Interceptors on the other hand are called each time a request is made, therefore it will fetch the token from local storage before each request. This ensures you are sending valid tokens instead of stale ones. Hope it helps.

import axios from 'axios'
import { BASE_URL } from './constants'

const instance = axios.create({
  baseURL: BASE_URL,
})

instance.interceptors.request.use(
    (config) => {
      const token = localStorage.getItem('Authorization')
      if (token) {
         config.headers.Authorization = `Bearer ${token}`
         config.headers["Content-Type"] = "application/json"
      } else {
         // Do something... Usually logout user.
      }
      return config
    }
)

export default instance

http-common.js should look something like above.

Upvotes: 4

Related Questions