2

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?

2
  • 2
    Store the token in session or local storage. Expose an endpoint to validate the token when the app starts up. If there's a token and it's still valid, then let them in without re-logging in. If there's no token or it's invalid, then kick them to the login screen and remove the token if it exists. Commented Nov 17, 2016 at 17:05
  • 1
    Also note that nothing on the client side isn’t secure, so you should always validate input on the server side (in this case, only serve the login-required pages after the user logs in and provides a token). Commented Nov 17, 2016 at 17:32

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Noticing mapStateToProps. Is this a Redux app? If so, can you share a little bit more about the authentication layer and how isAuthenticated is set?
this is a redux app. isAuthenticated is set in the reducer. I can edit my answer to show the code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.