lasith eshan
lasith eshan

Reputation: 128

Sending post request from axios with "Content-Type" : "application/x-www-form-urlencoded" gives an 401 Unauthorized response

I am sending a POST request to a server to fetch a token through axios with a Content-Type header of x-www-form-urlencoded. I tried the same with postman and it works fine. I'm sending a key value pair of grant_type and client_credentials in the request body.

This is my axios request:

axios.post(`${baseURI}/protocol/openid-connect/token`, data, {
  headers : {
    "Authorization" : "Basic " + token,
    "Content-Type" : "application/x-www-form-urlencoded"
  },
  withCredentials: true
}).then(response => {
  AUTH_TOKEN = response.data.access_token;
  console.log(response.data);
}).catch(error => {
  console.log(error.response);
})

The data object consists of the client_credentials.The same credentials gives a successful response in postman.

Upvotes: 9

Views: 12951

Answers (3)

gavenkoa
gavenkoa

Reputation: 48753

Modern Axios has automatic converted for url-encoded when Content-Type is set to application/x-www-form-urlencoded:

https://axios-http.com/docs/urlencoded

const data = {
  x: 1,
  arr: [1, 2, 3],
  arr2: [1, [2], 3],
  users: [{name: 'Peter', surname: 'Griffin'}, {name: 'Thomas', surname: 'Anderson'}],
};

await axios.post('https://postman-echo.com/post', data,
  {headers: {'content-type': 'application/x-www-form-urlencoded'}}
);

Above will be rendered as:

  {
    x: '1',
    'arr[]': [ '1', '2', '3' ],
    'arr2[0]': '1',
    'arr2[1][0]': '2',
    'arr2[2]': '3',
    'arr3[]': [ '1', '2', '3' ],
    'users[0][name]': 'Peter',
    'users[0][surname]': 'griffin',
    'users[1][name]': 'Thomas',
    'users[1][surname]': 'Anderson'
  }

At least Axois get form submission API (from 1995!) working ))

Upvotes: 0

Roman
Roman

Reputation: 21765

While @binary lobster solution is pretty concise, one might consider using qs library like this:

import qs from 'qs'

axios.post(`${baseURI}/protocol/openid-connect/token`,
  qs.stringify(data), {
  headers : {
    "Authorization" : "Basic " + token,
    "Content-Type" : "application/x-www-form-urlencoded"
  }
})
.then(/*...*/);

See more information here

Upvotes: 1

binary lobster
binary lobster

Reputation: 453

I had this exact same problem until I finally figured out that Axios needed the data object to be reformatted as a query string.

So make yourself a function like this:

function getQueryString(data = {}) {
  return Object.entries(data)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
    .join('&');
}

Pretty simple, just URI encoding all the parts of your object and joining them with &.

Then modify your code like this:

axios.post(`${baseURI}/protocol/openid-connect/token`,data, {
  headers : {
    "Authorization" : "Basic " + token,
    "Content-Type" : "application/x-www-form-urlencoded"
  },
  withCredentials: true,
  transformRequest: getQueryString
})
.then(/*...*/);

You can read about the different options, including transformRequest, for the request config here: https://github.com/axios/axios#request-config

(I'm still annoyed that this was necessary and not just handled by Axios but oh well.)

Upvotes: 19

Related Questions