Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send JWT token with fetch and cors to an Express server in Authorization headers?

I can retrieve JWT token from localStorage and send it in the req.body but for some reason, I'm unable to send it to the server with fetch() in headers.Authorization. I can log the token on the client-side but don't receive it on the server.

Client: React, Redux-Saga.

function* getInitialStateFetch(){

  var actionType = 'GET_INITIALSTATE_REDUCER';
  var path = 'react/listings28';

  var token = localStorage.getItem('my_tkn');
  console.log(token) // logs token

  var httpHeaders;

  if(token){
  httpHeaders = { 
    'Content-Type' : 'application/x-www-form-urlencoded', 
    'Accept' : 'application/json',
    'Authorization' : `Bearer ${token}`
  };
  } else {
    httpHeaders = { 
      'Content-Type' : 'application/x-www-form-urlencoded', 
      'Accept' : 'application/json'
    };
  }

  let options = {
    method: 'GET',
    mode: 'no-cors',
    headers: new Headers(httpHeaders),
    credentials: 'same-origin'
  };

  yield call(apiCall, path, options, actionType);
}

apiCall.js

export default function* apiCall(path, options, actionType){

  try {
    const response = yield call(fetch, `http://blah/${path}`, options);
    const data = yield call([response, response.json]);

    // call reducer
    yield put({type: actionType, payload: data});
  } catch (e) {
    console.log(e.message);
    console.log(`error api call for ${actionType}`);
  }
}

Server: Express.

router.get('/react/listings28', parserFalse, (req, res)=>{


  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3333');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
  res.setHeader('Access-Control-Allow-Credentials', true);

  var token = req.headers.Authorization; // nothing here

  console.log(`req headers below`);
  console.log(req.headers); // no Authorization here
}

req.headers screenshot from the server

req.headers screenshot from the server

like image 958
dan tenovski Avatar asked Dec 19 '17 01:12

dan tenovski


1 Answers

Finally figured it out. Cutting to the chase - it won't work because for the browser to send the Authorization header it needs to have mode: 'no-cors' but if you remove mode: no-cors then fetch() won't even try sending the request from localhost but will work fine if I upload bundle.js to the server. Also you need to set credentials to same-origin if you want to send cookies, by default in fetch() credentials is set to omit.

So a workaround for this would be to use webpack's dev proxy so you use your server rather than localhost.

like image 87
dan tenovski Avatar answered Sep 27 '22 21:09

dan tenovski