61

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

89
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
    }));
2
  • 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).
    – ggorlen
    Commented Mar 25 at 22:56
  • 1
    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.
    – ggorlen
    Commented Apr 14 at 2:00
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
  • 1
    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.
    – Rowland
    Commented Aug 6, 2017 at 22:23
6

You can pass headers as second parameter of fetch:

fetch(<your url>, {
  headers: {
     authorization: <whatever is needed here>
   }
})
4
  • want to pass all the values such as : Consumer Key: value Consumer Secret: value Access Token: value Access Token Secret: value Commented Aug 20, 2018 at 5:40
  • 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> }
    – Dario
    Commented Aug 20, 2018 at 8:17
  • This does not work. It throw error: "Response to preflight request doesn't pass access control check: It does not have HTTP ok status"
    – strix25
    Commented Mar 3, 2023 at 12:14
  • 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.
    – ggorlen
    Commented Mar 24 at 3:41
5
   headers: {
      'Authorization': `Bearer ${localStorage.getItem("token")}`,
      'Accept': 'application/json',
       'Content-Type': 'multipart/form-data;
  },
1
  • 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.
    – ggorlen
    Commented Mar 24 at 3:38
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));

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
  • 1
    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)
    – Fastnlight
    Commented Apr 23 at 21:04
  • Will do, thanks. Toughts about my explanation for the header?
    – L.Blondy
    Commented Apr 23 at 21:07
  • 4
    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. Commented Apr 23 at 21:10
  • 1
    Is it against the rules even if relevant to the topic?
    – L.Blondy
    Commented Apr 23 at 21:13
  • 1
    See How to not be a spammer. These links should be included in your profile, not your answers.
    – Nick
    Commented Apr 24 at 5:33

Not the answer you're looking for? Browse other questions tagged or ask your own question.