Skip to content

Authorization flow example #826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
olegakbarov opened this issue Sep 30, 2015 · 19 comments
Closed

Authorization flow example #826

olegakbarov opened this issue Sep 30, 2015 · 19 comments

Comments

@olegakbarov
Copy link

Do you guys interested in authorization flow example (Redux + React Router)? If so what are the key requirements to it?
We got some kind of it, but it is slightly verbose.

@gaearon
Copy link
Contributor

gaearon commented Oct 2, 2015

There may be some examples in Awesome Redux.
I think this is pretty popular question so we should probably include some example.

@olegakbarov
Copy link
Author

i'd love to create one if you'll outline the requirements! 📄

@hedgerh
Copy link
Contributor

hedgerh commented Oct 5, 2015

@olegakbarov What kind of requirements are you interested in? If you are interested in style, see the other examples and base yours off of those. Files like webpack.config.js, server.js, and others can be re-used from the existing examples.

You should also try and keep it as simple as possible. Take a stab at it and people can give you feedback.

@mewwts
Copy link

mewwts commented Oct 19, 2015

I'd love a simple guide to working with JWTs in redux. 👍

@elithrar
Copy link

https://preact.gitbooks.io/react-book/content/flux/auth.html is also a good example on how to handle this.

@Nicktho
Copy link

Nicktho commented Oct 27, 2015

I'd love a simple guide to working with JWTs in redux. 👍

After having implemented this in a production application i'm going to strip it out as a redux-jwt package, stay tuned.

@ferdinandsalis
Copy link

@Nicktho sweet. Look forward to it.

@HriBB
Copy link

HriBB commented Nov 4, 2015

+1 for redux-jwt. Let us know when it's ready for testing ;)

Do you use react-router? I'm having problems implementing auth with react-router, redux and redux-router. I think the entire community is having problems with it, and we should address this issue.

@olegakbarov
Copy link
Author

I'm not quite sure how to implement the server the redux example way — i mean we gotta have some async api, right?

@gaearon
Copy link
Contributor

gaearon commented Nov 4, 2015

I'm not quite sure how to implement the server the redux example way — i mean we gotta have some async api, right?

Nothing special.

@gaearon
Copy link
Contributor

gaearon commented Nov 4, 2015

Meaning, REST-like APIs (or really any kind of APIs) are fine to use with Redux. It doesn't care.

@HriBB
Copy link

HriBB commented Nov 4, 2015

Please add some documentation :) I would love to help, but this is beyond me. This problem has been bugging me for a few days now. I use redux-router and can't figure out how to do server rendering with jwt authentication (I store token in cookie). I know this is not the right place to ask, but maybe you can at least point me into the right direction. How or where should we load initial user data into store? How to pass store to the route onEnter hook with redux-router on server, when I have this

const history = createHistory();
const routes = getRoutes(requireAuth/*store does not exist yet*/);
const router = reduxReactRouter({ history, routes });
const store = configureStore(router, { user: { token: token } });

Do we dispatch inside requireAuth? How do we handle this in development? For example I use webpack-hot-middleware and in dev I don't do server rendering, so how to load user in this case? At the moment I have two different requireAuth functions for server and client. But it feels wrong so I decided to stop and understand the situation. Would love to read some more docs, especially for redux-router.

This is my server code

// Render react app
app.use((req, res) => {
  console.info('==> Render react application:', req.url);

  // Get auth token
  const token = req.cookies.token;

  function requireAuth(nextState, replaceState) {
    const isLoggedIn = Boolean(token);
    if (!isLoggedIn) {
      replaceState({
        nextPathname: nextState.location.pathname
      }, '/login');
    }
  }

  // Do the redux magic
  const history = createHistory();
  const routes = getRoutes(requireAuth);
  const router = reduxReactRouter({ history, routes });
  const store = configureStore(router, { user: { token: token } });

  // Run the redux-router
  store.dispatch(match(req.url, (error, redirectLocation, renderProps) => {
    if (error) {
      console.log(error);
      return res.status(500).end('Internal server error');
    }
    if (redirectLocation) {
      return res.status(301).redirect(redirectLocation.pathname);
    }
    if (!renderProps) {
      return res.status(404).end('Not found'); // TODO: render 404 on client?
    }

    function renderReactApp() {
      // Render react app
      const content = ReactDOMServer.renderToString(
        <div className="cb">
          <Provider store={store}>
            <ReduxRouter {...renderProps}/>
          </Provider>
        </div>
      );
      const initialState = store.getState();
      // Inject content and initial state into html
      const html = template.replace('${content}', content).replace('${data}', JSON.stringify(initialState));
      // Return final version of html back to middleware
      return html;
    }

    function fetchComponentData(dispatch, components, params) {
      const needs = components.reduce( (prev, current) => {
        return (current.needs || [])
          .concat((current.WrappedComponent ? current.WrappedComponent.needs : []) || [])
          .concat(prev);
      }, []);
      const promises = needs.map(need => dispatch(need(params)));
      return Promise.all(promises);
    }

    // Hey ho, here we go!
    fetchComponentData(store.dispatch, renderProps.components, renderProps.params)
      .then(renderReactApp)
      .then(html => res.end(html))
      .catch(err => res.end(err.message));

  }));

});

Keep up the good work!

@gaearon
Copy link
Contributor

gaearon commented Nov 4, 2015

Please create a StackOverflow question for this.
We're trying to keep issues for discussions, not for questions. (#838)

@mjrussell
Copy link

I've recently started a general purpose library for redux + auth with react-router since this question comes up so often. (and I'd like to reuse it across apps more easily) It uses a Higher Order Component method for enforcing both authentication and authorization on the "wrapped" components.

Maybe this is something that should be included in docs somewhere? Or eventually become part of rackt? In my experience using HOC as opposed to onEnter (from React-Router) is easier with redux.

https://github.com/mjrussell/redux-auth-wrapper

@sompylasar
Copy link

@mjrussell Nice! Recently I've implemented similar approach in a couple projects, but not published as a library. In case you want to compare some ideas, here it is: #1336 (comment)

@mjrussell
Copy link

@sompylasar cool, thanks I hadn't seen your approach before but definitely looks similar! Appreciate the link back in the other issue

@gaearon
Copy link
Contributor

gaearon commented Feb 23, 2016

This is a really nice article on the subject: https://auth0.com/blog/2016/01/04/secure-your-react-and-redux-app-with-jwt-authentication/

@mxstbr
Copy link
Contributor

mxstbr commented Feb 24, 2016

Don't know if people have seen this yet: https://github.com/mxstbr/login-flow

@johnstew
Copy link

The article that @gaearon pointed out is excellent. Pretty much covers everything you would need to do when handling authentication with JWT. I would try and build from this.

@timdorr timdorr closed this as completed Jul 10, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests