Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-admin JWT authentication refresh token problem

I want to implement my own authProvider for react-admin but I'm stuck.
I use a Django-Rest-Framework backend and a JWT token authentication system.
I want to refresh the JWT token if it's almost expired before every request. According to the documentation the authProvider's checkAuth function gets called before every API call, which is true. My problem is that with my code it doesn't wait for the promise to finish and it uses the old access token which results in a 401 and I get redirected to the login page. Any guidance what am I missing?

import jwt from 'jsonwebtoken';


export default {
    login: async ({ username, password }) => {
        const request = new Request('http://localhost:8000/api/token/', {
            method: 'POST',
            body: JSON.stringify({ username, password }),
            headers: new Headers({ 'Content-Type': 'application/json' }),
        });

        const response = await fetch(request);
        if (response.status < 200 || response.status >= 300) {
            throw new Error(response.statusText);
        }
        const { refresh, access } = await response.json();
        localStorage.setItem("refreshToken", refresh);
        localStorage.setItem("accessToken", access);
    },

    logout: params => {
        console.log("logout");
        localStorage.setItem('accessToken', "");
        localStorage.setItem('refreshToken', "");

        return Promise.resolve();
    },

    checkAuth: (params) => {
        const accessToken = localStorage.getItem('accessToken');
        const refreshToken = localStorage.getItem('refreshToken');

        if (accessToken && refreshToken) {
            console.log(accessToken);
            const { exp } = jwt.decode(accessToken);
            if (exp > (new Date().getTime() / 1000) - 10) {
                return Promise.resolve();
            } else {
                const request = new Request('http://localhost:8000/api/token/refresh/', {
                    method: 'POST',
                    body: JSON.stringify({ "refresh": refreshToken }),
                    headers: new Headers({ 'Content-Type': 'application/json' }),
                });

                const response = fetch(request)
                .then(response => {
                    if (response.status !== 200) {
                        throw new Error(response.statusText);
                    }
                    return response.json();
                })
                .then(({ token }) => {
                    localStorage.setItem('accessToken', token);
                    return Promise.resolve();
                });

                return response;
            }
        }
        return Promise.reject();
    },

    checkError: error => {
        if (error.status === 401 || error.status === 403) {
            return Promise.reject();
        }
        return Promise.resolve();
    },
    getPermissions: params => Promise.resolve(),
}
like image 305
ilo Avatar asked Feb 14 '20 20:02

ilo


People also ask

How do you refresh JWT tokens in React JS application?

React Refresh Token with JWT overview – A legal JWT must be added to HTTP Header if Client accesses protected resources. – With the help of Axios Interceptors, React App can check if the accessToken (JWT) is expired (401), sends /refreshToken request to receive new accessToken and use it for new resource request.


1 Answers

Can you try something like that

checkAuth: async (params) =>

And

  const request = new Request(...);

  let data;
  const response = await fetch(request);
  if (response.ok) data = await response.json()
  else throw new Error(response.statusText);

  if (data && data.token) {
      localStorage.setItem('accessToken', data.token);
      console.log(data.token);
      return Promise.resolve();
  } else return Promise.reject();
like image 178
CraftyMonkey Avatar answered Nov 15 '22 06:11

CraftyMonkey