1

I've been trying to get a login working using the Resource Owner Password Grant oAuth, however I can't seem to make it work.

I didn't build the backend I'm sending the request to, I'm using Invision Power Board's. I cannot find any example requests using a simple fetch so I'm just not sure if I'm doing anything wrong.

Here's my request being sent client-side:

const form = {
  'grant_type': 'password',
  'username': 'username',
  'password': 'pass',
  'scope': 'profile',
  'client_id': 'client_id',
}
  var formBody = [];
  for (var property in form) {
    var encodedKey = encodeURIComponent(property);
    var encodedValue = encodeURIComponent(form[property]);
    formBody.push(encodedKey + "=" + encodedValue);
  }
  formBody = formBody.join("&");
  await fetch(`https://example.com/oauth/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    },
    body: formBody
  })

All I get back is an error:

{
    "error": "invalid_request",
    "error_description": "request must be a POST request"
}

Did I format this the wrong way or am I missing something? I've been following the oAuth docs but maybe I've misunderstood how to do this.

Is it a problem with my server?

Edit - Example request with reqbin:

POST /oauth/token HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 85

grant_type=password&username=username&password=pass&scope=profile&client_id=client_id

Strangely enough the response here is:

{
    "error": "invalid_client"
}
lpetrucci
  • 1,285
  • 4
  • 22
  • 40
  • I see you have adapted my answer and still got the error. Are you using this code on the client-side or the server-side? Your tags say `node.js`, but Node.js does not have a native `fetch()` function. – Niklas E. Apr 25 '20 at 15:42
  • 1
    I'm using it client-side. Sorry, should've specified. – lpetrucci Apr 25 '20 at 15:44
  • Ok, I cannot find another mistake. The next step would be to test if it is caused by the server. If your stuff is not hosted local, you can check that by using https://reqbin.com/ Select "POST" and under content "FORM URL" and send the same body. – Niklas E. Apr 25 '20 at 15:48
  • Edited my question with the result. Strangely enough I get a "Client_id" error with reqbin. At least that must been it's not my server, right? – lpetrucci Apr 25 '20 at 15:58
  • Ok that is very strange. I'd read the manual of that API your using again and very carefully if I were you. I have no more ideas. Is there a proxy in between? Does the API want an X-Auth header? Have you done something wrong entirely else where? – Niklas E. Apr 25 '20 at 16:03
  • Unfortunately there's no more docs, so kind of lost here. The request is as simple as it can get so I have no idea how I could get it wrong. I'll try asking support, thank you so much for helping either way! – lpetrucci Apr 25 '20 at 16:09
  • @NiklasE. turns out the error disappears if I use a trailing slash, I'm an absolute moron. Thanks for fixing my code! – lpetrucci Apr 25 '20 at 18:31

2 Answers2

0

You are using the POST method but your request body is not a valid application/x-www-form-urlencoded file.

See how to convert an object to an urlencoded string and send it here: https://stackoverflow.com/a/37562814/7638119

Niklas E.
  • 1,848
  • 4
  • 13
  • 25
  • And also use `'Content-Type'` and not `'content-type'`. The convention is to use kebab case with the first letter of each word as upper case. – Niklas E. Apr 25 '20 at 15:39
  • I have made both changes suggested but the error persists. This also happens through Postman btw. – lpetrucci Apr 25 '20 at 15:40
0

According to the spec, Password flow requires user's credentials as well as client credentials. But I don't see your request has Authorization header.

Mikhail Kopylov
  • 2,008
  • 5
  • 27
  • 58