Using an authorization header with Fetch in React Native

I'm trying to use fetch in React Native to grab information from the Product Hunt API. I've obtained the proper Access Token and have saved it to State, but don't seem to be able to pass it along within the Authorization header for a GET request.

Here's what I have so far:

var Products = React.createClass({
  getInitialState: function() {
    return {
      clientToken: false,
      loaded: false
    }
  },
  componentWillMount: function () {
    fetch(api.token.link, api.token.object)
      .then((response) => response.json())
      .then((responseData) => {
          console.log(responseData);
        this.setState({
          clientToken: responseData.access_token,
        });
      })
      .then(() => {
        this.getPosts();
      })
      .done();
  },
  getPosts: function() {
    var obj = {
      link: 'https://api.producthunt.com/v1/posts',
      object: {
        method: 'GET',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + this.state.clientToken,
          'Host': 'api.producthunt.com'
        }
      }
    }
    fetch(api.posts.link, obj)
      .then((response) => response.json())
      .then((responseData) => {
        console.log(responseData);
      })
      .done();
  },

The expectation I have for my code is the following:

  1. First, I will fetch an access token with data from my imported API module
  2. After that, I will set the clientToken property of this.state to equal the access token received.
  3. Then, I will run getPosts which should return a response containing an array of current posts from Product Hunt.

I am able to verify that the access token is being received and that this.state is receiving it as its clientToken property. I am also able to verify that getPosts is being run.

The error I'm receiving is the following:

{"error":"unauthorized_oauth", "error_description":"Please supply a valid access token. Refer to our api documentation about how to authorize an api request. Please also make sure you require the correct scopes. Eg \"private public\" for to access private endpoints."}

I've been working off the assumption that I'm somehow not passing along the access token properly in my authorization header, but don't seem to be able to figure out exactly why.


Example fetch with authorization header:

fetch('URL_GOES_HERE', { 
    method: 'post', 
    headers: new Headers({
        'Authorization': 'Basic '+btoa('username:password'), 
        'Content-Type': 'application/x-www-form-urlencoded'
    }), 
    body: 'A=1&B=2'
});

It turns out, I was using the fetch method incorrectly.

fetch expects two parameters: an endpoint to the API, and an optional object which can contain body and headers.

I was wrapping the intended object within a second object, which did not get me any desired result.

Here's how it looks on a high level:

fetch('API_ENDPOINT', OBJECT)  
  .then(function(res) {
    return res.json();
   })
  .then(function(resJson) {
    return resJson;
   })

I structured my object as such:

var obj = {  
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Origin': '',
    'Host': 'api.producthunt.com'
  },
  body: JSON.stringify({
    'client_id': '(API KEY)',
    'client_secret': '(API SECRET)',
    'grant_type': 'client_credentials'
  })
}

I had this identical problem, I was using django-rest-knox for authentication tokens. It turns out that nothing was wrong with my fetch method which looked like this:

...
    let headers = {"Content-Type": "application/json"};
    if (token) {
      headers["Authorization"] = `Token ${token}`;
    }
    return fetch("/api/instruments/", {headers,})
      .then(res => {
...

I was running apache.

What solved this problem for me was changing WSGIPassAuthorization to 'On' in wsgi.conf.

I had a Django app deployed on AWS EC2, and I used Elastic Beanstalk to manage my application, so in the django.config, I did this:

container_commands:
  01wsgipass:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'

The following code snippet should work if you're using the bearer token :

const token = localStorage.getItem('token')

const response = await fetch(apiURL, {
        method: 'POST',
        headers: {
            'Content-type': 'application/json',
            'Authorization': `Bearer ${token}`, // notice the Bearer before your token
        },
        body: JSON.stringify(yourNewData)
    })