Add default axios header after login nextjs - reactjs

I'm using Next.js for my app, and currently have an API route that sets a JWT as a cookie. Throughout the app, I'm using Axios to fetch all of my data from external APIs, and after a user logs in I need to set that cookie as a default request header on every API call to make sure that a user has been authenticated. The basic flow is like this:
The login form sends a post request to my API route at /api/auth/login, passing the username and password and returning the JWT, and setting it as a cookie. Once the idToken cookie has been set I need to add that as an authentication header to every API request within my Axios instance, seen as adapter here. How can I go about getting this done?
My handle login function:
const handleLogin = async (values: ValuesProps) => {
const response = await axios.post('/api/auth/login', values);
if (response.status !== 200) {
throw new Error(response.statusText);
}
};
Which speaks to api/auth/login:
import { NextApiRequest, NextApiResponse } from 'next';
import { setCookie, parseCookies } from 'nookies';
import { adapter } from 'utils/api/config';
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== 'POST') {
res.status(500).json('Only POST requests allowed at this route.');
} else {
const { data } = await adapter.post(AUTH.login, JSON.stringify(req.body));
const cookies = parseCookies();
setCookie({ res }, 'idToken', data.token, {
maxAge: 30 * 24 * 60 * 60,
path: '/',
});
api.defaults.headers.Authorization = `Bearer ${cookies['idToken']}`
res.status(200).json(data);
}
};
export default handler;
As you see here I tried adding adapter.defaults.headers.Authorization as a global default, but I'm not seeing it in my request headers. What's the best way to go about setting this globally?

You could use axios.create. It is a factory that creates new instances of axios. So you write a function
import axios from "axios";
export const axiosInstance = async () =>{
// you need to be careful in next.js for adding cookies.
// You could be on the server or on client. this code will work for client assuming that you will be using on client side
// I belive you are using `parser` to get cookies. get the token
const yourToken="whatever"
const axiosClient = axios.create({
baseURL: 'baseUrlHere',
timeout: 1000,
headers: {
'Accept': 'application/vnd.GitHub.v3+json',
// this is how u set in your code
'Authorization': `Bearer ${cookies['idToken']}`
}
});
return axiosClient
}
Then import this in anywhere you want to use:
const {data}=await axiosInstance().post("/auth")
Technically this should work

You can set default header to all axios request by command:
const token = getCookie('token')
axios.defaults.headers.common["idToken"] = token

Related

Easy way to append token key to request data for every request with React Query

I have to add a token that is created upon login and put in cookies into my request data to every fetch request I make. I'm currently doing it by using a custom hook that will add it every time so I don't have to add it multiple times. Is there an easier way? Maybe with axios?
Here is my custom hook:
import { useQuery as useBaseQuery } from 'react-query';
import axios from 'axios';
const fetcher = async (url, options) => {
const token = Cookies.get('TOKEN');
const { data } = await axios.get(url, {
data: { ...options, 'TOKEN': token },
});
return data;
};
const useQuery = (queryKey, query, options) => {
return useBaseQuery(queryKey, async () => {
return await fetcher(query, options);
});
};
export default useQuery;
and is used like this:
import useQuery from './useBaseQuery';
const requestData = {
method: 'GET',
path: pathToUrl,
};
export default function useGetActionAlerts() {
return useQuery('actionAlerts', '/bin/user', requestData);
}
You need to use interceptor, from documentation
You can intercept requests or responses before they are handled by then or catch.
https://axios-http.com/docs/interceptors

Go Api returning Unauthorized

i am new learner of GoLang+React. So that i started a project to learn. I made a RESTful Api with GoLang. Api Link. i made a login system with that api. And successfully i can login and set user data to sessionStorage. But the problem is when i am trying to logout a user by hit the logout endpoint of api with axios. First time it shows Unauthorized. and second time its showing Network Error.
Here is the Request code:
logout = () => {
const user = JSON.parse(sessionStorage.getItem('userData'));
const token = user.token;
const uid = user.id;
const url = "http://localhost:8000/logout"
axios.post(url,{"user_id":uid},{"Authorization":`Bearer ${token}`}).then((response) => response.json()).then((result) => {
let responseJson = result;
console.log(responseJson);
}).catch((error) => {
console.log(error);
})
}
Note: by client application i can logout successfully. But by axios i cant.
You need to provide auth headers under headers property of Axios config object:
axios.post(
url,
{ user_id: uid },
{ headers: { 'Authorization': `Bearer ${token}` } }
)
Explanation:
This is the axios post method signature, check docs:
axios.post(url[, data[, config]])
And the 3rd parameter config should have this interface:
{
...
baseURL?: string;
headers?: any; // this is for headers
params?: any;
....
}
I fixed that problem with adding this code to my package.json file
"proxy":"http://localhost:your_port"

how to post headers with axios in react

Hi i have this problem:
i made and API with an auth JWT runs perfect and my front is in react so i need only one component its a simple app, so in my App.jsx i have my axios post to get the token and then i pass my token through the component, then i receive the props in the component and i saw the token but when i pass to the header like i test in postman, so nothing happens, and if i try the front and in the API i disable the JWT in my route works perfectly so i let my code next
const Cards = (props) => {
//console.log(props.auth.token);
//axios connection
const apiCall = async () =>{
let config = {
headers: {
'Authorization': `Bearer ${props.auth.token}`
}
}
console.log(config);
try {
const res = await clientAxios.post('/api/games', config,
{
console: 'nintendo',
game: 'super mario',
duration: '60hs'
},)
console.log(props.auth.token);
} catch (error) {
console.log(error.status);
}
}
apiCall();
Instead of sending the token with each request, set the token in axios' default headers like so:
window.axios.defaults.headers.common['Authorization'] = `Bearer ${jwtToken}`;

Axios request interceptor not working on browser refresh

I am using axios interceptor in my react app to pass the token for each request.
I initially call the setupAxiosInterceptors method after I login (See code below). This works perfectly fine until I refresh the browser.
const registerSucessfulLoginForJwt = (username, token) => {
sessionStorage.setItem(USER_NAME_SESSION_ATTRIBUTE_NAME, username)
setupAxiosInterceptors(createJwtAuth(token)) //Calling the axios interceptor at the time of login
}
See below the setupAxiosInterceptors method
const setupAxiosInterceptors = (token) => {
Axios.interceptors.request.use((config) => {
if(isUserLoggedIn()) {
config.headers.authorization = token
sessionStorage.setItem('authorization', token)
}
return config
})
}
Any thought on how to fix this so it works at all time?
I was able to find a solution to my problem. I create an ApiSetup.js file where I create a custom axios instance which could use for all requests.
const request = axios.create({
baseURL: API_PATH_BASE
})
request.interceptors.request.use(config => {
const currentUser = AuthenticationService.getLoggedInUser() //You can get the user directly from the cookie or session storage...
if(currentUser.userName) {
config.headers.Authorization = currentUser.userToken
}
return config
}, err => {
console.log(err)
return Promise.reject(err)
})
export default request

React-Adal returns 401 with POST request but 200 with GET request

I'm trying to send a POST request to an API that is hosted in Azure and is authenticated through Azure Active Directory. I'm using React with React-Adal to send my requests. I configured react-adal using the GitHub repo and this tutorial to guide me.
adalConfig.js
import { AuthenticationContext, adalFetch, withAdalLogin, adalGetToken } from 'react-adal';
export const adalConfig = {
tenant: 'ad5842d4-1111-1111-1111-111111111111',
clientId: '1f89aa20-1111-1111-1111-111111111111', //ClientID of the ReactClient application
endpoints: {
demoApi: 'e7926712-1111-1111-1111-111111111111', //ClientID of the DemoApi
microsoftGraphApi: 'https://graph.microsoft.com'
},
postLogoutRedirectUri: window.location.origin,
redirectUri: 'https://localhost:44394/',
cacheLocation: 'sessionStorage'
};
export const authContext = new AuthenticationContext(adalConfig);
export const adalDemoApiFetch = (fetch, url, options) =>
adalFetch(authContext, adalConfig.endpoints.demoApi, fetch, url, options);
export const adalTokenFetch = () =>
adalGetToken(authContext, adalConfig.endpoints.demoApi);
export const withAdalLoginApi = withAdalLogin(authContext, adalConfig.endpoints);
When I use the adalDemoApiFetch with a GET request it works fine and returns 200 with the list of schedules.
const url = `https://localhost:44322/api/Schedules/GetAllSchedules`;
const response = await adalDemoApiFetch(axios.get, url);
console.log(response);
const schedules = response.data;
When I use the same adalDemoApiFetch with a POST to add a new schedule to the list it returns a 401.
const url = `https://localhost:44322/api/Schedules/AddSchedule`;
const azureADID = authContext.getCachedUser();
const token = authContext.acquireToken("e7926712-1111-1111-1111-111111111111");
console.log(token);
const options = {
beginningDateTime: this.state.begDateTime.toJSON(),
endindDateTime: this.state.endDateTime.toJSON(),
userID: this.state.userID,
azureADID: azureADID.profile.oid
};
const response = await adalDemoApiFetch(axios.post, url, options);
console.log(response);
I also tried copying out the token and using it in Postman to make the call and it still returns 401. When I use the token that is returned from the function below it works just fine.
export const adalTokenFetch = () =>
adalGetToken(authContext, adalConfig.endpoints.demoApi);
I use axios to call it in the code below and it works just fine.
const url = `https://localhost:44322/api/Schedules/AddSchedule`;
const azureADID = authContext.getCachedUser();
const token = await adalTokenFetch();
console.log(token);
const options = {
beginningDateTime: this.state.begDateTime.toJSON(),
endindDateTime: this.state.endDateTime.toJSON(),
userID: this.state.userID,
azureADID: azureADID.profile.oid
};
const response = await axios.post(url,
{
data: options
},
{
headers: {
"Authorization": `Bearer ${token}`
}
}
);
console.log(response);
What am I doing wrong? Why would it work with a GET request and not with the POST request? Am I missing something?
I tried working with Axios too. Seems that using axios it is unable to authorize the bearer token. Try using the Adalfetch that fixed the problem for me.
You need to tell adalApiFetch you are using POST method instead of GET. It defaults to GET, that is why that works ootb. Use the options object.

Resources