Updating the axios instance header failed after login to the application - javascript

I am developing an application using React js in Redux architecture
and used axios for http requests.
I have two container classes one is login and another one is home
page. In routes class i import both the container classes.
In home page container i import one action and that action imports
one axios instance variable
export var Instance_Variable = axios.create({
baseURL: URL,
headers: {
"AUTH-TOKEN": localStorage.getItem("AuthToken")
}
});
In my scenario,
the routs file will import these instance variable while importing home page class.
While login i get the auth token from the response and set it to the local storage. After logging in there was one request made in home page and respond with unauthorized(401 - The auth token validation done in application).
I am view the network tab in browser and the request made with the header "AUTH-TOKEN" : null
How do i update the instance after logging in to the application
Note: The request are works well after refreshing the application after loggin

Hello I know it’s a very old question but today I also faced this same issue and Hopefully able to solve this problem also
So, when you call the 'login API URL with Axios, if this request succeeded then you have set the header in Axios '.then' block like they said here
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
Note: for this, you must have to use Axios interceptor

It is better to use an axios interceptor that sets header for every request like below:
axios
.interceptors
.request
.use(function (config) {
if (cookie.load('auth-token')) {
config.headers['AUTH-TOKEN'] = cookie.load('auth-token');
}
return config;
}, function (error) {
return Promise.reject(error);
});

Related

How to revalidate a user in nuxt

In my nuxt project, i get a token from the backend that identifies the user. I tie this token to a vuex prop and save it in localstorage, so the user doesnt have to re authenticate when the page is refreshed.
To revalidate the user only when the page is actually refreshed, i wrote a beforemount function in the highest level, which is the default layout
beforeMount() {
const token = localStorage.getItem('user-token')
console.log(token)
if (token) {
this.$axios.defaults.headers.common.Authorization = token
this.$store.dispatch('auth/setToken', token)
}
}
In the next step, the router on protected pages should check if the authstate is true, which is only true if the vuex localstorage prop is set. Since i only need that on certain pages, i wrote a router middleware thats only loaded on these pages
export default function (context) {
if (!context.store.getters['auth/isAuthenticated']) {
return context.redirect('/auth?login')
}
}
Problem is, the middleware runs before the beforeMount according to the docu, which creates the problem that the middleware checks for a token which is set later and kicks the user out.
Since the only thing that comes before router middleware is global middleware, my plan was to write the reauth as global middleware. But somehow, the middleware is also called on every router change, not only before the site is created aka page refresh. This would execute the function way too often.
The goal is to set the token before the route validate based on the token, only on page refresh, since the rest is taken care of by vuex.

Next.js redirect from an API route

I am building a back-office app that requires users to sign in.
I have 2 external APIs:
API A : to manage user accounts and sessions
API B : to perform CRUD actions on another database (unrelated to users database)
The problem is that I don't want users to be able to perform calls to API B if their session is not valid. So I added some API endpoints in Next (under pages/api) that do the following actions:
verifying the validity of the session against API A
if session is valid: continue to step 3, if not: redirect to page /login
make the call to API B
Everything works fine if the session is valid but it fails if the session is not valid.
I have tried
res.redirect(307, '/login').end()
and
res.writeHead(307, { Location: '/login' }).end()
but it didn't work. It fails even by specifying the whole path (http://localhost:3000/login). What I don't understand is that I am successfully redirected to my /login page if I make the request directly from the browser (GET http://localhost:3000/api/data). It doesn't work when I make the request with Axios inside a React component.
Any idea how I can fix this?
As #juliomalves and #yqlim explained, I had to make the redirect manually based on the response of the API.
Faced same problem solve using below code:
Api
res.status(200).json({ success: "success" }) //add at last of the api to give response
page
import Router from 'next/router'
let res = await fetch('api', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
if (res.status == 200) {
Router.push('/location')
}
Answer is correct as #Jules Grenier sayes,but provided an example
You do not need .end(). Have you tried res.redirect(307, '/login')?
In Next.js v12 and v13, the following works for me.
// /api/example.js
const handler = async function (req, res) {
// custom logic
if (failed)
return res.redirect(307, '/login')
}
export default handler;
The API request must be initiated by a <form>.
redirect will not work with <fetch>

Best place to fetch data for authed users in Vue app?

Hi I'm fetching a arrays of posts from my express API in the Home.vue which is protected by route guards.
<script>
export default {
created() {
this.$store.dispatch('fetchPosts')
}
}
</script>
fetchPosts action:
async fetchPosts(context) {
try {
const res = await api.get('/posts', {
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`
}
})
context.commit('SET_POSTS', res.data)
context.commit('SET_ERROR', null)
} catch(err) {
console.log(err.response.data)
context.commit('SET_ERROR', err.response.data)
}
}
In my action I commit a mutation which sets the posts object to res.data. I only want to fetchPosts when user logs in since I have a mutation which adds the post to the db and updates the posts state, when user adds a post. But because I route back to the home screen this causes the created() hook to run again, re-fetching data on each post req. App of course work fine but could be more efficient. What can I do to resolve better enhance my app?
You could check that you do not already have the state populated.
If it's empty make the API call, otherwise do nothing.
Having guards is a good thing. Depending of your app and the way you want to handle authed users, you could also wire a global middleware to your router. This will add more generic code and could be used on several places, hence less errors/duplication.
Here is an interesting article about this: https://markus.oberlehner.net/blog/implementing-a-simple-middleware-with-vue-router/
The rest of your code looks fine!

Next.js handle 0Auth authorization with MoneyButton

I am attempting to implement 0Auth user authorization for my Next.js app using MoneyButton API. I am able to trigger the authorization request with client.requestAuthorization('auth.user_identity:read','http://localhost:3000');
And it works smoothly redirecting me to MoneyButton permission consent and back to my app with the code and state params in URL -> ?code=6aa72eef702eb710cd22715d797cf7d27e06532a&state=38984b9d-3af0-48f1-8b5f-3fa47f4dfd9d
There is client.handleAuthorizationResponse(); method for handle the response. That method automatically gets the tokens from the query parameters and set the internal state of the client to use them. Also it saves the credentials in local storage, so the user stays logged in with Money Button if they close the browser.
But unfortunately i don't know how to use this method after being redirected back to my app. I am using it in Authuser function, but requestAuthorization triggers redirect to moneybutton, so rest of the function is not executed. How to use handleAuthorization after being redirected back to application?
https://docs.moneybutton.com/docs/api/auth/api-auth-jsclient.html - here are the MoneyButton docs
I am also considering to add MoneyButton as custom 0Auth provider in NextAuth.js to make integrations faster in the future.
Authuser.js
const { MoneyButtonClient } = require('#moneybutton/api-client')
export default function Authuser () {
const client = new MoneyButtonClient('MYAPP_OAUTH_IDENTIFIER_CODE');
client.requestAuthorization('auth.user_identity:read','http://localhost:3000');
client.handleAuthorizationResponse();
const refreshToken = client.getRefreshToken();
client.setRefreshToken(refreshToken)
}
You need to make sure that client.handleAuthorizationResponse(); is run client side (not server side render) after the moneybutton auth has redirected back:
if ((new URLSearchParams(window.location.search)).has('code')) {
await client.handleAuthorizationResponse()
const accessToken = await client.getValidAccessToken()
...
}

Axios - Different headers for Express Request

I start to develop an SSR React-Redux application, and i have a problem with axios headers.
What is the proper way to set different header for each Express request?
Express.get('*', async (req, res) => {
axios.defaults.headers.common = req.headers['my-customer-id'];
// first axios get request
// second axios get request
// thirth axios get request
//... initialization React App
});
With this approach, axios default headers are overwritten from last Express request.
I try to create different axios instance with axios.create(), but i don't know where and how to save the instance, for use inside application modules.
there is a different between global headers and instance only headers:
// affects the global instance
axios.defaults.headers.common['Auth-Token'] = 'foo bar';
// affects to a single instance
axiosInstance.defaults.headers['Auth-Token'] = 'foo bar';
this works for me inside an expressjs app too, with different services (instances of axios)
You can create a new custom instance of axios using create.
const customAxios = axios.create({
headers: {...req.headers['my-customer-id']}
});
Now use customAxios to make the request
customAxios.get(...)

Categories