How to fix 401 (Unauthorized) error for GET request in Vue - node.js

I log in to an app then make an axios GET request to the database. However, a 401 (Unauthorized) error is returned. How can I fix this?

401 means the request didn't take the token in request headers.
I think you need to check if the token exists
let token = localStorage.getItem('user')
if (token) {
axios.defaults.headers.common['Authorization'] = token;
} else {
axios.defaults.headers.common['Authorization'] = null;
}
or if you want to make all requests bring token, you can user axios interceptors to intercept all requests to add authorization headers and handle the response.
axios.interceptors.request.use((config) => {
if (store.getters.token) {
config.headers['x-token'] = getToken();
}
return config;
});
axios.interceptors.response.use( response=>{
const res = response.data
if (res.code != 200) {
Message({
message: res.data || "Error",
type: 'error'
})
if(res.code == 401) {
MessageBox.confirm(res.data, '重新登录', {
confirmButtonText: '确定',
type: 'warning'
}).then(() => {
store.dispatch('user/logout')
window.location.replace('/login')
})
}
return res
} else {
return res
}
})

Related

Memory Leak with axios-module from Nuxt

I have a memory leak using #nuxtjs/axios. I don't really know if it's my code or the plugin.
My project requires 2 axios instances to run.
One to get an "anonymous token" to be allowed to access the API.
And a second one to use that token and make my API calls.
const createDefaultClient = (agent, $axios, $appInsights, inject) => {
const defaultClient = $axios.create({
withCredentials: true,
httpsAgent: agent
})
defaultClient.setBaseURL(
process.server ? 'http://localhost:3000' : window.location.origin
)
defaultClient.onResponseError(error => {
logError(error, $appInsights)
return Promise.reject(error)
})
inject('defaultClient', defaultClient)
return defaultClient
}
const createApiClient = (
agent,
$axios,
$cookies,
$appInsights,
defaultClient,
inject,
request
) => {
const apiClient = $axios.create({
withCredentials: true,
httpsAgent: agent
})
apiClient.setBaseURL(process.env.NUXT_ENV_BASE_API)
apiClient.onRequest(config => {
const cookieToken = $cookies.get(accessTokenCookieName)
if (cookieToken) {
config.headers.common.Authorization = `Bearer ${cookieToken}`
}
debug(`${config.__isRetryRequest ? 'Retry' : 'Request'}: ${config.url}`)
})
apiClient.onResponseError(async error => {
const originalRequest = error.config
debug(`Error ${get(error, 'response.status')}: ${error.config.url}`)
// if we get error 401 (token expiration) we will refresh the token and retry to access API
if (error.config && error.response && error.response.status === 401) {
originalRequest.__isRetryRequest = true
const refreshToken = $cookies.get(refreshTokenCookieName)
let fetchAnonymousToken = true
let response = null
// if we had a cookie try to refresh it
if (refreshToken) {
response = await defaultClient.$post(`/forms/refresh`, {
refreshToken
})
if (!response) throw new Error('Auth failure')
if (process.client) {
createAuthCookies($cookies, response, request)
}
fetchAnonymousToken = false
}
// else fetch an anonymous cookie
if (fetchAnonymousToken) {
response = await defaultClient.$get(`/forms/anonymous`)
if (!response) throw new Error('Auth failure')
if (process.client) {
createAuthCookies($cookies, response, request)
}
}
// resend API request with the new valid token
originalRequest.headers.Authorization = `Bearer ${get(
response,
'access_token'
)}`
return apiClient(originalRequest)
} else {
logError(error, $appInsights)
return Promise.reject(error)
}
})
inject('apiClient', apiClient)
}
export default function({ $axios, app, req }, inject) {
const { $cookies} = app
const agent = new https.Agent({
rejectUnauthorized: process.env.NODE_ENV !== 'development'
})
const defaultClient = createDefaultClient(agent, $axios, inject)
createApiClient(
agent,
$axios,
$cookies,
defaultClient,
inject,
req
)
}
Basically I've followed the doc here : https://axios.nuxtjs.org/extend
I've commented everything in my projet and without the API calls the memory get garbage collected.
Here the memory before the charge
Here after the charge
After a siege, we can clearly see that the memory won't go down :/
Please help me i'm desesperate..

How to get auth token for PowerBI REST API?

I am in the process of building a server-side app that is going to push the data into PowerBI's dataset. The only thing I'm struggling with is getting the bearer token to make a request to their API.
I'm getting the access token in the following way, however, I'm getting "401 Unauthorized" when using it in the request.
async getToken() {
const AuthenticationContext = adal.AuthenticationContext;
const context = new AuthenticationContext(`${ CONFIG.power_bi.authorityURI }/${ CONFIG.power_bi.tenantID }`);
return new Promise((resolve, reject) => {
context.acquireTokenWithClientCredentials(
CONFIG.power_bi.scope,
CONFIG.power_bi.clientID,
CONFIG.power_bi.clientSecret,
(error, tokenResponse) => {
if (error) {
console.log('PowerBI Token Acquire Error:', error);
return reject(tokenResponse == null ? error : tokenResponse);
}
console.log('PowerBI Token Acquired:', tokenResponse);
return resolve(tokenResponse);
}
);
});
}
async postRowsInDatasetTable() {
const token = await this.getToken().then(({ accessToken }) => accessToken);
const groupId = '{groupId}';
const datasetId = '{datasetId}';
const tableName = '{tableName}';
try {
const result = await axios.post(
`https://api.powerbi.com/v1.0/myorg/groups/${groupId}/datasets/${datasetId}/tables/${tableName}/rows`,
{
rows: [{
"status": "Deal",
"date": "2021-02-10T10:55:01.706Z"
}]
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-type': 'application/json'
}
}
);
} catch (error) {
console.log(error);
}
}
The thing is that data push functionality is working just fine with a token which I took from PowerBI's documentation page, where they provide example API calls, as it is populated automatically based on currently logged-in user (e.g. https://learn.microsoft.com/en-us/rest/api/power-bi/pushdatasets/datasets_postrowsingroup), which means I am simply getting the wrong token.
Could anyone please advise how to get the appropriate token, as I found nothing in the documentation?
Thanks

Get JWT token in redux

I am using JWT to handle authentication and I have a update new password function. My problem is that how do I pass this JWT to my server in the UpdatePasswordAction ? Actually, I have that JWT in my cookies but when I submit the data to the server, the data is not passed correctly. Do I pass it right?
From my server, the JWT can not be retrieved.
console.log(JSON.stringify(req.cookies));// -> {}
console.log(req.headers.authorization);// -> undefined
In my User.actions.jsx, what I want to do is to get the token stored in cookies and pass the updatePasswordState which contains current password, new password, and new confirmed password.
import { Cookies } from 'js-cookie';
export const UpdatePasswordAction = (updatePasswordState) => {
return async (dispatch) => {
try {
// what I do is to pass the new password and JWT to the server to handle new password update
const token = Cookies.get('jwt');
const res = await axios.patch(`http://127.0.0.1:3000/users/updateMyPassword`, updatePasswordState, token);
const { data } = res;
dispatch({ type: UserActionTypes.UPDATE_PASSWORD_SUCCESS, payload: data });
alert('Update Password Successfully');
} catch (error) {
if (error.response) {
dispatch({
type: UserActionTypes.UPDATE_PASSWORD_FAIL,
payload: error.response.data.message,
});
console.log(error.response.data.message);
}
}
};
};
In my server, I have a middleware to check whether the user is login or not.
exports.protect = catchAsync(async (req, res, next) => {
//Getting token and check of it's there
let token;
console.log(JSON.stringify(req.cookies));// -> {}
console.log(req.headers.authorization);// -> undefined
if (
req.headers.authorization &&
req.headers.authorization.startsWith('Bearer')
) {
token = req.headers.authorization.split(' ')[1];
} else if (req.cookies.jwt) {
token = req.cookies.jwt;
}
if (!token) {
return next(
new AppError('You are not logged in! Please log in to get access.', 401)
);
}
// rest jwt decode and verification
});
Any solution?
You are not correctly sending the data to the server. The axios#patch signature is this:
axios#patch(url[, data[, config]])
So you should change it to something like this:
await axios.patch(`http://127.0.0.1:3000/users/updateMyPassword`, updatePasswordState, {
headers: {
"Authorization": token
}
});
And on your server side you can access the Authorization header with req.headers.authorization

Axios Interceptor not intercepting error statuses when API called is made

I am trying to intercept all the 401 responses and then redirecting them to another page.
This is what I have done for the instance
const instance = axios.create({
baseURL: "https://api.example.com/",
withCredentials: true
});
// Add a response interceptor
instance.interceptors.response.use(
function(response) {
return response;
},
function(error) {
if (401 === error.response.status) {
console.log('intercepted');
window.location = "/login";
} else {
return Promise.reject(error);
}
}
);
export default instance;
And in my API services file, I am calling axios using the instance.
import axiosInstance from "../utils/axiosInstance";
const response = await axiosInstance.post("/player/new", bodyFormData);
This API will return 401 however the interceptor isn't catching it and I can see the failed request in the network dev tools.
You should add the interceptor to your axios instance instead of axios itself, as pointed out in the documentation:
instance.interceptors.response.use(
function(response) {
return response;
},
function(error) {
if (401 === error.response.status) {
console.log('intercepted');
window.location = "/login";
} else {
return Promise.reject(error);
}
}
);

How to logout once jwt token is expired

I am working on a web-app using node.js and vue.js, I am doing authentication and maintaining session using jwt and passport.js using passport-jwtstrategy
I have done all the things from creating jwt to protecting routes all the things now my issue is while generating jwt I am passing expiresIn:3600 so I want to auto-logout my user from Ui and remove token from localStorage once it has been one hour
On decoding my jwt I am getting
{
"name": "Dheeraj",
"iat": 1571896207,
"exp": 1571899807
}
So how can I get the real-time when to logout
In my auth.js vue store file my logout code when user clicks on logout is
logout({ commit }) {
return new Promise((resolve, reject) => {
localStorage.removeItem('jwt-token')
localStorage.removeItem('user-name')
commit('setAuthUser', null)
resolve(true)
})
},
In the same file, I have a method getAuthUser which is running whenever a page is loading or reloading to check to protect rout and guestUser
getAuthUser({ commit, getters }) {
const authUser = getters['authUser']
const token = localStorage.getItem('jwt-token')
const isTokenValid = checkTokenValidity(token)
if (authUser && isTokenValid) {
return Promise.resolve(authUser)
}
commit('setAuthUser', token)
commit('setAuthState', true)
debugger
return token
}
So how can I logout once my token is expired
Anyone out here please guide me how can I logout once the token is expired
Edit
In my router.js file
router.beforeEach((to, from, next) => {
store.dispatch('auth/getAuthUser')
.then((authUser) => {
const isAuthenticated = store.getters['auth/isAuthenticated']
if (to.meta.onlyAuthUser) {
if (isAuthenticated) {
next()
} else {
next({ name: 'login' })
}
} else if (to.meta.onlyGuestUser) {
if (isAuthenticated) {
next({ name: 'welcome' })
} else {
next()
}
} else {
next()
}
})
})
from my auth file I am calling get authUser which I have already mention above
for checking token validity I am using this code
function checkTokenValidity(token) {
if (token) {
const decodedToken = jwt.decode(token)
return decodedToken && (decodedToken.exp * 1000) > new Date().getTime()
}
return false
}
but it returns false when I am on login page and there is no token there but once I am loged in it shows null
My global api file
import axios from 'axios';
export default () => {
let headers = {
'cache-control': 'no-cache'
};
let accessToken = localStorage.getItem('jwt-token');
if (accessToken && accessToken !== '') {
headers.Authorization = accessToken;
};
return axios.create({
baseURL: 'http://localhost:8086/',
headers: headers
});
}
Refer to the axios documentataion: https://github.com/axios/axios
import axios from 'axios';
export default () => {
let headers = {
'cache-control': 'no-cache'
};
let accessToken = localStorage.getItem('jwt-token');
if (accessToken && accessToken !== '') {
headers.Authorization = accessToken;
};
const instance = axios.create({
baseURL: 'http://localhost:8086/',
headers: headers
});
instance.interceptors.response.use((response) => {
if(response.status === 401) {
//add your code
alert("You are not authorized");
}
return response;
}, (error) => {
if (error.response && error.response.data) {
//add your code
return Promise.reject(error.response.data);
}
return Promise.reject(error.message);
});
return instance;
}

Resources