Vue API data is gone on window refresh - vue.js

When I login I am redirected to secret page which needs JWT authentication. Data is loaded on secret page. And when I refresh the window - data is lost. How can I fix it?
I use eventBus to send a JWT token to sibling template.
Login view method on submit:
submitSignin() {
console.log("submit!");
this.submitted = true;
this.$v.$touch();
if (this.$v.$invalid) {
return; // stop here if form is invalid
}
axios
.post("http://localhost:3000/auth/login", this.authData)
.then((res) => {
this.token = res.data.token;
this.authData.email = "";
this.authData.password = "";
this.$v.$reset();
this.successMsg = "You Sign in Successfully!";
this.$router.push({ path: "/auth/all-users" });
this.$nextTick(() => {
eventBus.$emit("sendtoken", this.token);
});
})
.catch((err) => {
console.log(err.response.data.message);
this.errorMsg = err.response.data.message;
});
},
SecretPage view:
<script>
export default {
name: "SecretPage",
data() {
return {
users: [],
};
},
methods: {
loadUsers() {
let self = this;
eventBus.$on("sendtoken", (token) => {
axios
.get("http://localhost:3000/auth/all-users", {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((response) => {
console.log(token);
console.log(response.data.users);
self.users = response.data.users;
})
.catch((err) => {
console.log(err);
});
});
},
},
mounted() {
this.loadUsers();
},
};
</script>
loaded users

Related

Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST'

I'm on a page that uses a vue component and one of my patch routes is saying I'm un-authenticated.
<template>
...
<button #click="editPost(attributes.attributes.post_id)"></button>
...
</template>
<script>
export default {
data() {
return {
info: null,
message: null,
postTitle: "",
postContent: ""
}
},
methods: {
editPost(id) { // not working, 401 unauthenticated
console.log('edit post clicked', id);
axios.patch('http://127.0.0.1:8000/api/posts/' + id, {
headers: {
Authorization: 'Bearer 3d58d6cd66e134a59b3a9373a2b4a233e55d00107b9251f654c5c92a2276a1c5'
}
})
.then((response) => {
this.info = response.data;
// this.message = 'Success';
console.log(this.info);
})
.catch((error) => {
console.log(error, error.response.data.message);
this.message = error.response.data.message;
})
},
deletePost(value){
console.log('delete post clicked', value);
}
},
mounted() {
axios.get('http://127.0.0.1:8000/api/posts', { // working as expected, authenticated
headers: {
Authorization: 'Bearer 3d58d6cd66e134a59b3a9373a2b4a233e55d00107b9251f654c5c92a2276a1c5'
}
})
.then((response) => {
this.info = response.data;
this.message = 'Success';
console.log(this.info);
})
.catch((error) => {
console.log(error, error.response.data.message);
this.message = error.response.data.message;
})
}
}
</script>
I dont understand how this can be since I have to authenticate to get the posts on page load and they load fine, with authentication using a Bearer token in header?
Why is the call to axios using a PATCH not working? The PATCH call works in postman fine also.

When using axios interceptors, API calls are looping for 401 error

I am trying to use interceptors in VueJs to request refresh token using axios. I have written some logic with interceptors and dispatch to store. When token expires and i reload the page, api post call is attempted infinitely forming a loop.to stop it i have to close the browser or logout and refresh the page. And the other error is "import/no-cylce" on my axios.js file when trying to import store. Below is my code, any suggestions are helpful, thanks.
axios.js
import axios from 'axios';
// eslint-disable-next-line import/no-cycle
import store from '#/store';
// eslint-disable-next-line import/no-cycle
// axios.defaults.headers.common.Authorization = `Bearer ${sessionStorage.getItem('accessToken')}`;
const getAPI = axios.create({
baseURL: 'http://127.0.0.1:5000',
});
getAPI.interceptors.response.use(undefined, (error) => {
if (error.config && error.response.status === 401) {
const result = 'test interceptor';
console.log(result);
store.dispatch('refreshToken')
// eslint-disable-next-line camelcase
.then((access_token) => {
axios.request({
headers: { Authorization: `Bearer ${this.$store.state.accessToken}` },
});
console.log(access_token);
});
}
});
// eslint-disable-next-line import/prefer-default-export
export { getAPI };
Below is Vuex store file, I created a refresh function to perform refresh.
import Vue from 'vue';
import Vuex from 'vuex';
// eslint-disable-next-line import/no-cycle
import { getAPI } from '#/axios';
// eslint-disable-next-line camelcase
Vue.use(Vuex);
export default new Vuex.Store({
state: {
// accessToken: JSON.parse(localStorage.getItem('access_token')) || null,
// refreshToken: JSON.parse(localStorage.getItem('refresh_token')) || null,
accessToken: localStorage.getItem('access_token') || null,
refreshToken: localStorage.getItem('refresh_token') || null,
APIData: '',
},
getters: {
loggedIn(state) {
return state.accessToken != null;
},
},
mutations: {
// eslint-disable-next-line camelcase
updateLocalStorage(state, { access_token, refresh_token }) {
// localStorage.setItem('accessToken', JSON.stringify(access_token));
// localStorage.setItem('refreshToken', JSON.stringify(refresh_token));
localStorage.setItem('access_token', access_token);
localStorage.setItem('refresh_token', refresh_token);
// eslint-disable-next-line camelcase
state.accessToken = access_token;
// eslint-disable-next-line camelcase
state.refreshToken = refresh_token;
},
// eslint-disable-next-line camelcase
updateAccessToken(state, access_token) {
// eslint-disable-next-line camelcase
state.accessToken = access_token;
},
destroyToken(state) {
state.accessToken = null;
state.refreshToken = null;
},
},
actions: {
userLogin(context, credentials) {
return new Promise((resolve, reject) => {
getAPI.post('/login', {
email: credentials.email,
password: credentials.password,
})
.then((response) => {
context.commit('updateLocalStorage', { access_token: response.data.access_token, refresh_token: response.data.refresh_token });
resolve();
console.log('\'access token\'', response.data.access_token);
console.log('\'refresh token\'', response.data.refresh_token);
// console.log(context.state.accessToken);
// console.log(context.state.refreshToken);
})
.catch((error) => {
reject(error);
});
});
},
userLogout(context) {
if (context.getters.loggedIn) {
// context.commit('updateLocalStorage', null);
context.commit('destroyToken');
}
},
refreshToken(context) {
return new Promise((resolve, reject) => {
console.log(context.state.refreshToken);
getAPI.post('/refresh', {
// refresh_token: context.state.refreshToken,
headers: { Authorization: `Bearer ${context.state.refreshToken}` },
})
.then((response) => {
console.log('New access token granted');
context.commit('updateAccessToken', response.data.access_token);
console.log(context.state.accessToken);
resolve(response.data.access_token);
})
.catch((error) => {
console.log('\'error in refresh:\'', error);
reject(error);
});
});
},
},
});
Below is view file for protected data.
About.vue
created() {
getAPI.get('/userList', {
// eslint-disable-next-line no-undef
headers: { Authorization: `Bearer ${this.$store.state.accessToken}` },
},
console.log(`Bearer ${this.$store.state.accessToken}`))
.then((response) => {
this.$store.state.APIData = response.data;
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
},
Also, i'm getting this error earlier. I used axiosAuth instead of axio
ex-:
const getAPI = axiosAuth.create({
baseURL: 'http://127.0.0.1:5000',
});

How to add header to get request in vue js?

I am taking data from api, how to send get request with token after login?
It shows error createError.js?2d83:16 Uncaught (in promise) Error: Request failed with status code 401
export default new Vuex.Store({
state: {
users: []
},
mutations: {
setUsers(state, args){
state.users = args;
}
},
actions: {
login({ }, arg) {
axios.post('login/', { username: arg.username, password: arg.password })
.then((response) => {
console.log(response);
let accessToken = response.token.data;
localStorage.setItem('token', accessToken);
localStorage.setItem('user', response.data.user);
axios.defaults.headers.common['Authorization'] = accessToken;
window.isSignedIn = true;
router.push('/');
})
.catch((error) => {
console.log(error);
})
},
getUsers({ commit }){
let { data } = axios.get('v1/user/list/');
commit('setUsers', data);
}
}
})
Depends which authentication you are using. Try with:
axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
Other HTTP authentication schemes.

How to update view inside axios promise and after store dispatch?

I have a simple vue app where I'm trying to add simple authentication. Inside my login.vue, I use axios to authenticate the user via ajax and store the token returned by the api in the store then redirect to a new page (ex: dashboard.vue).
The problem is that the token is saved but the view is not updated, can't call router.push() ...
Any ideas why isn't it working ? Thanks
Login.vue
methods: {
authenticate () {
var dataLogin = {
email: this.login,
password: this.password
}
var headers = { headers: { 'Content-type': 'application/json', 'Accept': 'application/json' } }
axios.post(config.apiUrl, dataLogin, headers)
.then(response => {
this.$store.dispatch('login', response.data).then(() => {
// if there is no error go to home page
if (!this.$store.getters.error) {
this.$router.push('/')
}
})
})
.catch(error => {
this.errorMessage = error.response.data.message
this.authError = true
})
}
}
The store function just save the token with localStorage
const actions = {
login (context, data) {
context.commit('authenticate', data)
}
}
const mutations = {
authenticate (state, data) {
localStorage.setItem('user-access_token', data.access_token)
}
}
You are calling a then() handler when you dispatch the action.
But your action does not return a promise.
So return a promise in your action as follows:
const actions = {
login (context, data) {
return new Promise((resolve, reject) => {
context.commit('authenticate', data)
resolve()
})
}
}
Also chain your promises for better readability
axios.post(config.apiUrl, dataLogin, headers)
.then(response => {
return this.$store.dispatch('login', response.data)
}).then(() => {
// if there is no error go to home page
if (!this.$store.getters.error) {
this.$router.push('/')
}
})
.catch(error => {
this.errorMessage = error.response.data.message
this.authError = true
})

VUE : Updating store data after login

I'm having an issue where the store data "menus" is not updated after i do a login.
Appearantly.. the object "loggedInUser" is not sat before i call "getMenus".. I'm not sure what i'm doing wrong here...
PS! When debugging in chrome, i notice that loggedInUser is "null" when entering the api call (see api.js codesnippet).
Login.vue (method) :
methods: {
doLogin() {
this.errorMessage = '';
this.loading = true;
let userCredentials = {
'username': this.loginEmail,
'password': this.loginPassword
};
this.$store.dispatch('tryLogin', {
'login': this.loginEmail,
'password': this.loginPassword
}).then((response) => {
this.$store.dispatch('getMenus')
.then((response) => {
this.$router.push('/')
});
});
}
},
Menus.vue (same as /)
computed: {
menus() {
return this.$store.getters.menus
}
},
created() {
this.$store.dispatch('getMenus')
},
methods: {
viewMenu: function(item) {
console.log("=> View Menu : " + item.Name)
this.$router.push('/viewmenu/' + item.Id)
}
}
}
store.js (getMenus action AND tryLogin)
actions: {
getMenus({ commit, getters }) {
api.getMenus(getters.loggedInUser)
.then(menus => {
commit('UPDATE_MENUS', menus);
});
},
tryLogin({ commit }, credentials) {
api.tryLogin(credentials)
.then(loggedInUser => {
commit('LOGGED_IN_USER', loggedInUser);
});
},
api.js (getMenus function)
getMenus(loggedInUser) {
var hostname = 'http://myurl'
var config = {
headers: {
'Content-Type': 'application/json'
}
}
var endpointUrl = hostname + '/api/Menu/GetMenus';
if (loggedInUser != null){
endpointUrl = hostname + '/api/Menu/GetMenusForSubCompany/' + loggedInUser.encryptedsubcompanyid;
}
return axios.get(endpointUrl, config)
.then(response => response.data);
},
From your store.js snippet, it seems you forget to return the promise.