score:2
please check if i have correctly configured axios.interceptors.
i think it works. but i suggest that you should test it carefully.this is a good article to refer https://blog.liplex.de/axios-interceptor-to-refresh-jwt-token-after-expiration/
have i placed it in the right place, i.e. above theitems class. ?
you should create a service function to wrap axios and api configs,and interceptor of course
axios.interceptors.response is assigned to the interceptor variable. what should i do with this variable?
it is just a variable used to define the interceptor. don't care about it. if you want to avoid assigning it, just do it inside a function like this automating access token refreshing via interceptors in axios
i have to wait 24 hours to test whether it works, or is it possible in a different way, faster?
you can change the token saved in your localstorage, and do that
where should i put 'client_id', 'secret_id', 'grant_type'?
if you store it inside localstorage, it's accessible by any script inside your page (which is as bad as it sounds as an xss attack can let an external attacker get access to the token).
don't store it in local storage (or session storage). if any of the 3rd part scripts you include in your page gets compromised, it can access all your users' tokens.
the jwt needs to be stored inside an httponly cookie, a special kind of cookie that's only sent in http requests to the server, and it's never accessible (both for reading or writing) from javascript running in the browser.
score:1
please check if i have correctly configured axios.interceptors.
from what i can see the configuration seems ok, as it's the same of this answer https://stackoverflow.com/a/53294310/4229159
have i placed it in the right place, i.e. above theitems class. ?
that is something that i can't answer, every application is different, it's not the best place to put it, but might be ok for an example. in your app however it should be together with all the api calls (for example)
axios.interceptors.response is assigned to theinterceptor variable. what should i do with this variable?
as you can see, the variable that got answered from the call to /refresh_token
for assigned to config.headers['authorization'] = 'bearer ' + response.data.access_token;
if you backend reads from there the auth value you should be fine
i have to wait 24 hours to test whether it works, or is it possible in a different way, faster?
you should wait unless the backend can change that, and expire the token in less time (eg in 5 or 2 minutes)
where should i put 'client_id', 'secret_id', 'grant_type'?
seems like the backend should have that, unless they are public ones... you are probably the best to know whether that belongs to the config for the call or if you are authenticating with them. if you are authenticating with them and they are the ones that grant you a token, then you shouldn't put it in the client side, as it is a security risk
score:1
1) configuration looks fine to me. but your solution won't work when there are multiple parallel requests and all of them trying to refresh auth token at the same time. believe me this is a issue is really hard to pin point. so better be covered upfront.
2) no. not the right place. create a separate service (i call it api.service) and do all the network/api commutation using that.
3) there is no use of interceptor variable. you can avoid assigning it to a variable.
4) if have control over the api you can reduce the timeout for a bit. also i think 24 hours is bit too long. else no option i guess.
5) not sure you have to deal with them.
bellow is a working code of api.service.ts. you might have to change few things here and there to fit that in to your application. if you get the concept clearly it wont be hard. also it cover multiple parallel request problem as well.
import * as querystring from 'query-string';
import axios, { axiosrequestconfig, method } from 'axios';
import { accountservice } from '../account.service'; //i use account service to authentication related services
import { storageservice } from './storage.service'; //i use storage service to keep the auth token. inside it it uses local storage to save values
var instance = axios.create({
baseurl: 'your api base url goes here',
});
axios.defaults.headers.common['content-type'] = 'application/json';
export const apiservice = {
get,
post,
put,
patch,
delete: deleterecord,
delete2: deleterecord2
}
function get<t>(controller: string, action: string = '', urlparams: string[] = [], queryparams: any = null) {
return apirequest<t>('get', controller, action, null, urlparams, queryparams);
}
function post<t>(controller: string, action: string = '', data: any, urlparams: string[] = [], queryparams: any = null) {
return apirequest<t>('post', controller, action, data, urlparams, queryparams);
}
function put<t>(controller: string, action: string = '', data: any, urlparams: string[] = [], queryparams: any = null) {
return apirequest<t>('put', controller, action, data, urlparams, queryparams);
}
function patch<t>(controller: string, action: string = '', data: any, urlparams: string[] = [], queryparams: any = null) {
return apirequest<t>('patch', controller, action, data, urlparams, queryparams);
}
function deleterecord(controller: string, action: string = '', urlparams: string[] = [], queryparams: any = null) {
return apirequest<any>('delete', controller, action, null, urlparams, queryparams);
}
function deleterecord2<t>(controller: string, action: string = '', urlparams: string[] = [], queryparams: any = null) {
return apirequest<t>('delete', controller, action, null, urlparams, queryparams);
}
function apirequest<t>(method: method, controller: string, action: string = '', data: any, urlparams: string[] = [], queryparams: any = null) {
var url = createurl(controller, action, urlparams, queryparams);
var options = createrequestoptions(url, method, data);
return instance.request<t>(options)
.then(res => res && res.data)
.catch(error => {
if (error.response) {
//handle error appropriately: if you want to display a descriptive error notification this is the place
} else {
//handle error appropriately: if you want to display a a generic error message
}
throw error;
});
}
function createurl(controller: string, action: string = '', urlparams: string[] = [], queryparams: any = null) {
let url = controller + (action ? '/' + action : '');
urlparams.foreach(param => {
url += '/' + param;
});
let params = '';
if (queryparams) {
params += '?' + querystring.stringify(queryparams);
}
return url += params;
}
function createrequestoptions(url: string, method: method, data: any, responsetype?: any) {
var authtoken = storageservice.getauthtoken();
var jwttoken = authtoken != null ? authtoken.authtoken : '';
var options: axiosrequestconfig = {
url,
method,
data,
headers: {
'authorization': 'bearer ' + jwttoken
},
}
if (responsetype) {
options.responsetype = responsetype;
}
return options;
}
let isrefreshing = false;
let failedqueue: any[] = [];
const processqueue = (error: any, token: string = '') => {
failedqueue.foreach(prom => {
if (error) {
prom.reject(error);
} else {
prom.resolve(token);
}
});
failedqueue = [];
}
instance.interceptors.response.use(undefined, (error) => {
const originalrequest = error.config;
if (originalrequest && error.response && error.response.status === 401 && !originalrequest._retry) {
if (isrefreshing) {
return new promise(function (resolve, reject) {
failedqueue.push({ resolve, reject })
}).then(authtoken => {
originalrequest.headers.authorization = 'bearer ' + authtoken;
return axios(originalrequest);
}).catch(err => {
return err;
})
}
originalrequest._retry = true;
isrefreshing = true;
return new promise(function (resolve, reject) {
accountservice.refreshtoken()
.then(result => {
if (result.succeeded) {
originalrequest.headers.authorization = 'bearer ' + result.authtoken;
axios(originalrequest).then(resolve, reject);
processqueue(null, result.authtoken);
} else {
reject(error);
}
}).catch((err) => {
processqueue(err);
reject(err);
}).then(() => { isrefreshing = false });
});
}
return promise.reject(error);
});
cheers,
score:3
this is what i did before. your configuration is a little different from mine.
const baseurl = localstorage.getitem('domain');
const defaultoptions = {
baseurl,
method: 'get',
headers: {
'content-type': 'application/json',
}
};
// create instance
const axiosinstance = axios.create(defaultoptions);
// get token from session
const accesstoken = ...
// set the auth token for any request
instance.interceptors.request.use(config => {
config.headers.authorization = accesstoken ? `bearer ${accesstoken}` : '';
return config;
});
// last step: handle request error general case
instance.interceptors.response.use(
response => response,
error => {
// error
const { config, response: { status } } = error;
if (status === 401) {
// unauthorized request: maybe access token has expired!
return refreshaccesstoken(config);
} else {
return promise.reject(error);
}
}
});
i think this part should be separated with components - it will be placed on helpers or utils.
also, you have to wait for 24 hrs because refreshtoken() method is never called before 24 hrs.
you don't need to process client_id
, secret_id
, grant_type
right here.
Source: stackoverflow.com
Related Query
- Acquiring a new token with `axios.interceptors`
- Issue with cancelling axios .then logic with interceptors and cancel token
- Sending the bearer token with axios
- How to setup Axios interceptors with React Context properly?
- How to pass Header JWT Token with Axios & React?
- Cannot send form data with axios when using interceptors
- problem with using axios interceptors in react
- How to set cookie with JWT token in ReactJS frontend using Node, Express, Axios
- axios , login with api , handle token
- React Router Link with params not reloading page with new data from componentDidMount and Redux axios data fetching
- How to send axios put request with jwt token in reactjs
- Ruby on Rails does not include Authorization token on header when request by axios in React, but it does work with Postman
- Token Authentication with Axios in React
- How to Create Middleware for refresh token in Reactjs with axios and redux
- Why authorization token exists in axios interceptors even after deleting the token?
- How can I request a new access token after the existing token expires with the firebase refresh token?
- Axios post fails with 403 error code and showing CSRF token validation failed but works fine django api when passing csrftoken in header with Postman
- Axios: Using baseUrl in a separate file causes problems with setting authentication token in axios request headers
- Want to send JWT token in headers along with data using axios but getting this error : Cannot set headers after they are sent to the client
- post request in Axios with 400 or 401 - bearer token
- Axios Delete request with body and headers?
- Axios get in url works but with second parameter as object it doesn't
- Maintaining href "open in new tab" with an onClick handler in React
- How do I set multipart in axios with react?
- New React Native project with old version of react native
- Use Async/Await with Axios in React.js
- CSRF with Django, React+Redux using Axios
- How to fetch the new data in response to React Router change with Redux?
- How to mock history.push with the new React Router Hooks using Jest
- How to redirect from axios interceptor with react Router V4?
More Query from same tag
- nodemon app crashed after logging in with false credentials
- Why isn't my ReactJs App not updating correctly
- Can not update a component while rendering a different component
- React put query string into form's value attribute
- Is It Best Practice To Use MUI 5 ThemeProvider Only in "_app.js" or Is It Ok To Use On Every Component?
- Cannot make POST request with JSON from react/axios to restify server
- Set color of dropdown arrow on NavDropdown
- Reactjs - getDerivedStateFromProps() not updated the data using setState or Editing the data
- TypeScript type for value of key in object
- When to use constructors in React components?
- Conditional classes on single instances of component within a loop
- React SetState Twice in Same Function
- React-Native Button onPress not working
- Receiving data from server using reactjs
- Typing React Router Router Component? Confused
- How to change the URL with out actually routing to different page in react
- React / mxGraph: How to render Graph from external source, with functional react component?
- es6/Redux help: need help spreading state
- I have a button in my react app that i only want it to be pressed once
- Is there a way to modify the useState of another function?
- How to change an object value of a state array by using a specific array index
- Changing font size with respect to the change in screen resolution using styled-components in react
- Context Provider Type and get the value on other components
- Material ui DatePicker enable only year
- Ionic 5 changing grid size and applying style not working with react?
- Error when using if, when updating the state in react
- Trying to understand the paradigm of React
- Keep react-router routed-components for all history states
- Missing "key" prop for element in iterator react/jsx-key in React
- How to pass parameter to HTTP Get method from .Net Core + React