Jacob Lamont Jacob Lamont - 13 days ago 5
React JSX Question

User Authentication for API from React App

I have a simple API built in Nodal which allows a user to create a new job (essentially a work order for a service business). The API is using OAuth, so in order to create a new job, the user has to first obtain a token by authenticating via username and password.

The frontend is going to be built in React. In order to access the site, the user will have to log in with their username and password, at which point they'll be given a token to make API calls. Two questions:

1) How do I securely store the API token such that the user doesn't have to log in every time the page refreshes?

2) How do I use this same login step to determine if they have access to any given page within the frontend app?

Answer

This is the process I have used in my current project. When a user logs in, I take the token and store in localStorage. Then every time a user goes to any route, I wrap the component that the route serves in a hoc. Here is the code for the HOC that checks for token.

export function requireAuthentication(Component) {

    class AuthenticatedComponent extends React.Component {

        componentWillMount () {
            this.checkAuth(this.props.user.isAuthenticated);
        }

        componentWillReceiveProps (nextProps) {
            this.checkAuth(nextProps.user.isAuthenticated);
        }

        checkAuth (isAuthenticated) {
            if (!isAuthenticated) {
                let redirectAfterLogin = this.props.location.pathname;
                browserHistory.push(`/login?next=${redirectAfterLogin}`);
            }
        }

        render () {
            return (
                <div>
                    {this.props.user.isAuthenticated === true
                        ? <Component {...this.props}/>
                        : null
                    }
                </div>
            )

        }
    }

    const mapStateToProps = (state) => ({
        user: state.user
    });

    return connect(mapStateToProps)(AuthenticatedComponent);
}

Then in my index.js I wrap each protected route with this HOC like so:

<Route path='/protected' component={requireAuthentication(ProtectedComponent)} />

This is how the user reducer looks.

export default function userReducer(state = {}, action) {
    switch(action.type) {
        case types.USER_LOGIN_SUCCESS:
            return {...action.user, isAuthenticated: true};
        default:
            return state;
    }
}

action.user contains the token. The token can either come from the api when a user first logs in, or from localstorage if this user is already a logged in user.

Comments