Rowland
Rowland

Reputation: 1823

Setting authorization header in Fetch API

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?

Upvotes: 61

Views: 159175

Answers (6)

L.Blondy
L.Blondy

Reputation: 468

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

Upvotes: 0

ggorlen
ggorlen

Reputation: 57023

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));

Upvotes: 0

bechir majri
bechir majri

Reputation: 61

   headers: {
      'Authorization': `Bearer ${localStorage.getItem("token")}`,
      'Accept': 'application/json',
       'Content-Type': 'multipart/form-data;
  },

Upvotes: 6

Pankaj Bhardwaj
Pankaj Bhardwaj

Reputation: 2131

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
    }));

Upvotes: 90

Fabian Schultz
Fabian Schultz

Reputation: 18556

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) });

Upvotes: 19

Dario
Dario

Reputation: 6280

You can pass headers as second parameter of fetch:

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

Upvotes: 6

Related Questions