When you receive a token from passport authentication sites, you must save the token in your localStorage
browser. A dispatcher is Redux middleware. Ignore dispatch
if you are not using shorthand in your application. you can just use setState
here (a bit strange without shorthand).
client side:
Here's something like an API that returns a token.
saving tokens
axios.post(`${ROOT_URL}/api/signin`, { email, password }) .then(response => { dispatch({ type: AUTH_USER }); //setting state (Redux Style) localStorage.setItem('token', response.data.token); //saving token browserHistory.push('/home'); //pushes back the user after storing token }) .catch(error => { var ERROR_DATA; try{ ERROR_DATA = JSON.parse(error.response.request.response).error; } catch(error) { ERROR_DATA = 'SOMETHING WENT WRONG'; } dispatch(authError(ERROR_DATA)); //throw error (Redux Style) });
So, when you make some authenticated requests, you need to attach a token with the request in this form.
authenticated requests
axios.get(`${ROOT_URL}/api/blog/${blogId}`, { headers: { authorization: localStorage.getItem('token') } //take the token from localStorage and put it on headers ('authorization is my own header') }) .then(response => { dispatch({ type: FETCH_BLOG, payload: response.data }); }) .catch(error => { console.log(error); });
Here's my index.js: Token is checked every time, so even if the browser is updated, you can still set the state.
authenticates user
const token = localStorage.getItem('token'); if (token) { store.dispatch({ type: AUTH_USER }) } ReactDOM.render( <Provider store={store}> <Router history={browserHistory}> <Route path="/" component={App}> .. .. .. <Route path="/blog/:blogid" component={RequireAuth(Blog)} /> //ignore this requireAuth - that another component, checks if a user is authenticated. if not pushes to the index route </Route> </Router> </Provider> , document.querySelector('.container'));
All actions performed for sending establish a state.
my reducer file (Redux only), otherwise you can just use setState () in the index route file to provide state for the entire application. Each time a submission is called, it launches a similar reducer file, similar to this one, which sets the state.
state setting
import { AUTH_USER, UNAUTH_USER, AUTH_ERROR } from '../actions/types'; export default function(state = {}, action) { switch(action.type) { case AUTH_USER: return { ...state, error: '', authenticated: true }; case UNAUTH_USER: return { ...state, error: '', authenticated: false }; case AUTH_ERROR: return { ...state, error: action.payload }; } return state; }
Remove the token from the local storage to exit the system.
Warning: Use any other name, not token
, to save the token in the localStorage
browser
server side:
tailored to your passport file. You must set the title search. Here passport.js
const passport = require('passport'); const ExtractJwt = require('passport-jwt').ExtractJwt; const JwtStrategy = require('passport-jwt').Strategy; .. .. .. .. const jwtOptions = { jwtFromRequest: ExtractJwt.fromHeader('authorization'), //client side must specify this header secretOrKey: config.secret }; const JWTVerify = new JwtStrategy(jwtOptions, (payload, done) => { User.findById(payload._id, (err, user) => { if (err) { done(err, null); } if (user) { done(null, user); } else { done(null, false); } }); }); passport.use(JWTVerify);
In my router.js
const passportService = require('./services/passport'); const requireAuthentication = passport.authenticate('jwt', { session: false }); .. .. ..