62

I have a Node/Express backend and I'm consuming the API with a React Client. I want to be able to set the authorization header after a user is signed up. This ensures that subsequent requests are sent with the authorization header.

I can see how it's done in Axios here and how to retrieve the authorization header in Fetch here

Is it possible to do this with Fetch API and how?

0

6 Answers 6

91
var url = "https://yourUrl";
var bearer = 'Bearer ' + bearer_token;
fetch(url, {
        method: 'GET',
        withCredentials: true,
        credentials: 'include',
        headers: {
            'Authorization': bearer,
            'X-FP-API-KEY': 'iphone', //it can be iPhone or your any other attribute
            'Content-Type': 'application/json'
        }
    }).then(responseJson => {
        var items = JSON.parse(responseJson._bodyInit);
    })
    .catch(error => this.setState({
        isLoading: false,
        message: 'Something bad happened ' + error
    }));
Sign up to request clarification or add additional context in comments.

2 Comments

Good answer, but JSON.parse(responseJson._bodyInit); is a bit odd. I'd use the public JSON body parsing API: fetch().then(res => res.json()).then(data => console.log(data)) (error handling left as an exercise).
No problem, but you can still edit to improve your answer. Another thing: I don't think withCredentials is part of the fetch API. I think credentials: "include" does the job on its own.
19

As far as I know, there's no way to use default options/headers with fetch. You can use this third party library to get it to work, or set up some default options that you then use with every request:

// defaultOptions.js
const defaultOptions = {
  headers: {
    'Authorization': getTokenFromStore(),
  },
};

export default defaultOptions;

Then use the default options like:

import defaultOptions from './defaultOptions';

// With default options:
fetch('/auth', defaultOptions);

// With additional (non-default) options:
fetch('/auth', { ...defaultOptions, body: JSON.stringify(additionalData) });

1 Comment

Thank you. I use all of that but I think there should be a way to set authorization header with Fetch API. The issue is not making a request with it but setting it after authenticating the user such that in my network panel in the dev tool, for instance, I can see it set like other things.
6

You can pass headers as second parameter of fetch:

fetch(<your url>, {
  headers: {
     authorization: <whatever is needed here>
   }
})

4 Comments

want to pass all the values such as : Consumer Key: value Consumer Secret: value Access Token: value Access Token Secret: value
you can add those as keys to headers object: { authorization: <whatever is needed here>, 'consumer key': <value>, 'consumer secret': <value>, 'Access Token': <value>, 'Access token secret': <value> }
This does not work. It throw error: "Response to preflight request doesn't pass access control check: It does not have HTTP ok status"
This is too vague to need to be helpful. There are other answers that supersede this and show how to actually build the request, with correct syntax, leaving nothing to guesswork.
6
   headers: {
      'Authorization': `Bearer ${localStorage.getItem("token")}`,
      'Accept': 'application/json',
       'Content-Type': 'multipart/form-data;
  },

1 Comment

What does this add to the existing answers, like this one, which shows the whole fetch call? localStorage is irrelevant except for your particular case. Programmers will know how to adapt whatever means of retrieval they're using for the token, where it's a variable, env var, database, localStorage, HTTP endpoint... there's no need to add an answer for each of these sources.
0

Existing answers show the header but are either incomplete, promote poor practices and/or have irrelevant information.

Here's a minimal, complete, runnable example:

const url = "https://httpbin.org/bearer";
const token = "foobar";

fetch(url, {
  // credentials: "include", // may not be necessary
  headers: {
    Authorization: `Bearer ${token}`,
  }
})
  .then(response => {
    if (!response.ok) {
      throw Error(response.status);
    }

    return response.json();
  })
  .then(data => {
    console.log(data);
  })
  .catch(error => console.error(error.message));

Comments

0

In order to set a default header on your fetch request you have two choices:

1st choice: create a fetch wrapper

The best solution, while it may look like a simple task at forst glance, it can get quite tricky. You might use a library instead, I wrote this one.

2nd choice: create a helper to merge the default headers with the new ones.

Always keep in mind this one thing: your auth header has to be dynamic, you should read it everytime you make a fetch request. In order to stay safe, read it in a function call

const withDefaults = (headers) => {
   // for the Auth header make sure to read the value dynamically inside this function
   // if you were to read it outside the value would never change
   // the following also works with cookies
   const authHeader = localStorage.getItem('auth-header')
   // transform the headers from the params in an Header instance
   // this formats the keys in a consistent way 
   // eg both 'content-Type' and 'Content-type' are transformed to 'Content-Type' 
   const headersInstance = new Headers(headers) 
   // add the Authorization header if the headersInstance do not have it
   if(!headersInstance.has('Authorization')){
      headersInstance.set('Authorization', authHeader) 
   } 
    
   return headersInstance
} 

Usage

fetch('url here', {
   headers: withDefaults({ 'content-type': 'application/json' }), 
   // ...other options
   method: 'POST', 
   body: { hello: 'world'} 
}) 

Make it reusable

Our solution is not really reusable, the default headers are hard coded into our function

To solve that issue we can use a factory function

const createWithDefaults = (getDefaultHeaders) => {
  return (headers) => {
      const headersInstance = new Headers(headers) 
      new Headers(getDefaultHeaders()).forEach((val, key) => {
         if(!headersInstance.has(key)) {
             headersInstance.set(key, val) 
         } 
      })
      return headersInstance
   } 
} 

Notice that getDefaultHeaders is a function, this makes sure the default headers stay dynamic: they are evaluated inside if withDefaults

usage

const withDefaults = createWithDefaults(() => ({
   Authorization: localStorage.getItem('auth-header'),
   // other default headers
})) 

// then do the same as before
fetch('url here', {
   headers: withDefaults({ 'content-type': 'application/json' }), 
   // ...other options
   method: 'POST', 
   body: { hello: 'world'} 
})  

This way we never need to change the internals of the functions. We only need to change the arg passed to createWithDefaults

5 Comments

This one is ok, but you need to add disclosure to all your other posts that promote this library, or any of your others (such as tw-colors)
Will do, thanks. Toughts about my explanation for the header?
There's still the fact that every answer you've posted promotes your own libraries (usually without disclosure). Even with disclosure, it seems rather excessive to me.
Is it against the rules even if relevant to the topic?
See How to not be a spammer. These links should be included in your profile, not your answers.

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.