Giter VIP home page Giter VIP logo

Comments (2)

fgiarritiello avatar fgiarritiello commented on August 11, 2024 1

Thanks Jeff.
The server side is not using cookie so I will have to check the expiration manually on the client. That was very useful!

from redux-logic.

jeffbski avatar jeffbski commented on August 11, 2024

Here's some thoughts and ideas around JWT. Short answer is yes you can use redux-logic for things like auto-refreshing tokens and intercepting actions that need a valid JWT and refreshing before sending the action to the fetch logic.

Actual JWT creation and verification would be done server-side to keep things secure (since you don't want to go passing around your secret). And while redux-logic can be used on the server, most of these types of responses would be RPC style (request/response) so they would typically be done with a REST call or similar rather than an event based redux style call.

The server code that verifies JWT can also check to see when it is expiring and perform a refresh providing an updated cookie or header with the new JWT. If you are using a cookie to pass your JWT around then the client doesn't need to do much when it is refreshed, the browser just stores the new cookie. If you are not using cookies then you will want to look at the responses to see if they contain an updated JWT and store it appropriately.

So on the client you are basically showing them a login page until they have authenticated.

Login could just be it's own page where you simply post to the server and then once authenticated redirected to a different page or you can handle this like any async request (similar to any of the many examples) and when you receive the data you dispatch to update that you are authenticated and store the JWT if not using cookies.

You could certainly add some redux-logic code that sets a timer and performs a refresh before it expires.

const scheduleJWTRefreshLogic = createLogic({
  type: SCHEDULE_JWT_REFRESH,
  cancelType: LOGOUT, // cancel on action LOGOUT
  process({ getState, action, cancelled$ }, dispatch, done) {
    const refreshDelay = action.payload;
    const timer = setTimeout(() => {
      axios.post(url, data) // post to server to get refreshed JWT
        .then(resp => resp.data)
        .then(data => {
          const nextRefreshDelay = calcDelay(data.jwt);
          dispatch({ type: JWT_UPDATE, payload: data.jwt });
          dispatch({ type: SCHEDULE_JWT_REFRESH,
                     payload: nextRefreshDelay });
        })
        .catch(err => {
          console.error(err);
          dispatch({ type: ERROR, payload: err, error: true });
        })
        .then(() => done());  // done dispatching
    }, refreshDelay);

    cancelled$.subscribe(() => clearTimeout(timer));
  }
});

OR using Observables it could look like this

const scheduleJWTRefreshLogic = createLogic({
  type: SCHEDULE_JWT_REFRESH,
  cancelType: LOGOUT, // cancel on action LOGOUT

  processOptions: {
    failType: ERROR
  },
  
  process({ getState, action) {
    const refreshDelay = action.payload;
    return Observable.timer(refreshDelay) // return obs
      .mergeMap(() =>
        Observable.ajax({ url, method: 'POST', responseType: 'json' })  // POST to server to get refreshed JWT
         .map(ret => ret.response)
         .mergeMap(data => { // create a couple actions to dispatch
           const nextRefreshDelay = calcDelay(data.jwt);
           return Observable.of(
             { type: JWT_UPDATE, payload: data.jwt },
             { type: SCHEDULE_JWT_REFRESH,
                     payload: nextRefreshDelay }
           );
         })
       );
  }
});

As for your suggestion about checking JWT during validate, yes, you could do a check in the validate hook. It might look something like this.

This is an example of a centralized JWT validate logic separate from the fetching logic. You could also do the validates in each fetch logic itself.

// check the JWT token in the payload of FETCH_REPOS or FETCH_WIDGETS
// actions. The token could also just been stored in state.
// If expired or expiring soon, refresh before continuing
const checkJWTLogic = createLogic({
  type: [FETCH_REPOS, FETCH_WIDGETS], // action types or regexes
  validate({ getState, action }, allow, reject) {
    checkToken(action.jwt, getState())
      .then(jwt => {
        allow({
          ...action,
          jwt  // using the new or updated jwt token
        });
      })
      .catch(err => {
        console.error(err);        
        reject({ type: AUTH_ERR, payload: err, error: true })
      });
  }
});

function checkToken(jwt, state) {
  const expires = calcExpires(JWT); // negative if already expired
  if (expires < 0) { // expired
    return api.getJWTToken(state.x); // returns a promise to new JWT
  } else if (expires < THRESHOLD) { // expires soon
    return api.refreshJWTToken(jwt); // return a promise to refreshed JWT
  }
  // otherwise not expiring soon nothing to do, still valid
  return Promise.resolve(jwt); // promise to existing JWT    
}

from redux-logic.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.