Search code examples
reactjsauthenticationcorsfetch-apiharvest

Authentication Error when using mode: no-cors using fetch in React


I am building a React app that is pulling different stats from services for our internal developers (commits, tracked hours, etc)..

I am using fetch to grab API data from Harvest, a time tracking app. According to their docs, you can use basic HTTP authentication. When I use the app Postman, all is well and I can see the response just fine. Initially I used:

getHarvest(){
    // Set Harvest Headers
   const harvestHeaders = {
     method: 'GET',
     headers: {
       'Authorization': 'Basic xxxxxxxxxxxxxxx=',
       'Content-Type': 'application/json',
       'Accept': 'application/json',
       'Cache-Control': 'no-cache',
     }
   };

   fetch('https://factor1.harvestapp.com/projects/', harvestHeaders)
   .then( response => response.json() )
   .then( projects => {

    // Do some stuff


   } )
  }

This gives me an error in the console:

Fetch API cannot load https://myaccount.harvestapp.com/projects/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 404. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

So with that feedback I changed the function to look like this:

getHarvest(){
    // Set Harvest Headers
   const harvestHeaders = {
     method: 'GET',
     mode: 'no-cors',
     headers: {
       'Authorization': 'Basic xxxxxxxxxxxxxxx=',
       'Content-Type': 'application/json',
       'Accept': 'application/json',
       'Cache-Control': 'no-cache',
     }
   };

   fetch('https://factor1.harvestapp.com/projects/', harvestHeaders)
   .then( response => response.json() )
   .then( projects => {

    // do stuff


   } )
  }

But that results in an Authentication error:

GET https://myaccount.harvestapp.com/projects/ 401 (Unauthorized)

I'm not sure how I can get the response correctly. Am I doing something wrong? It seems odd to me that using the app Postman works but this doesn't. Thoughts? Thanks!


Solution

  • It doesn’t seem like the Harvest API is meant to be used with XHR or Fetch from Web applications.

    At least their docs don’t mention anything about using their API from XHR or Fetch, nor do those docs mention anything about Access-Control-Allow-Origin nor CORS in general.

    Instead the docs give examples of using the API with curl and with the Postman REST Client.

    And trying examples in the docs like below, the response has no Access-Control-Allow-Origin.

    curl -H 'Content-Type: application/xml' -H 'Accept: application/xml' \
      -u "[email protected]:password" https://example.harvestapp.com/account/who_am_i
    

    So it seems like the answer is: You can’t access the Harvest API with XHR/Fetch from a Web app.

    It works in Postman because Postman is not bound by the same-origin policy browsers enforce to prevent Web apps running in a browser from making cross-origin requests unless the site/endpoint the request is made to has opted in to using CORS (which it seems Harvest hasn’t opted into).