Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FormData autoserialize doesn't work, need to use getBuffer() #5498

Open
leaumar opened this issue Jan 25, 2023 · 6 comments
Open

FormData autoserialize doesn't work, need to use getBuffer() #5498

leaumar opened this issue Jan 25, 2023 · 6 comments

Comments

@leaumar
Copy link

leaumar commented Jan 25, 2023

Describe the bug

According to the docs you should be able to do a form submit with FormData simply with await axios.post(url, form, { headers: form.getHeaders() }). We've been debugging since yesterday and found that this doesn't work, we kept getting error responses from microsoft oauth, until we changed it to await axios.post(url, form.getBuffer(), { headers: form.getHeaders() });.

To Reproduce

I can't provide a true repro because it depends on an external service and I can't exactly give you our microsoft oauth values. But here's a simple nodejs repl script that demonstrates the problem if you have ms oauth values available. Interestingly, ms oauth responds with a 404 instead of a 400 when the request is malformed.

Code snippet

var FormData = require('form-data');
var axios = require('axios');

var oAuthClient = axios.create();
var clientId = '<your clientId here>';
var clientSecret = '<your clientSecret here>';
var scope = `api://${clientId}/.default`;
var tenantId = '<your tenant here>';

var url = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
var form = new FormData();

form.append('client_id', clientId);
form.append('client_secret', clientSecret);
form.append('grant_type', 'client_credentials');
form.append('scope', scope);

// remove .getBuffer() and get a 400/404
// with .getBuffer() you get 200 with a token
void oAuthClient.post(url, form.getBuffer(), {
  headers: form.getHeaders(),
}).then(console.info).catch(console.error);

Expected behavior

No response

Axios Version

1.2.2

Adapter Version

No response

Browser

No response

Browser Version

No response

Node.js Version

16.18.1

OS

No response

Additional Library Versions

form-data 4.0.0

Additional context/Screenshots

running webpack-bundled typescript on aws
@DigitalBrainJS
Copy link
Collaborator

DigitalBrainJS commented Jan 25, 2023

Can you make a successful authorization request with Postman? I suspect their Auth API should use application/x-www-form-urlencoded rather than multipart/form-data since the request does not contain binary data.

const {data} = await oAuthClient.post(url, {
  'client_id': clientId,
  'client_secret': clientSecret,
  'grant_type': 'client_credentials',
  'scope': scope
}, {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
});

From their docs (https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#protocol-details):

// Line breaks for legibility only

POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded    // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong 
&client_secret=JqQX2PNo9bpM0uEihUPzyrh    // NOTE: Only required for web apps. This secret needs to be URL-Encoded.

@theVJagrawal
Copy link

Can I work on this issue? I don't know a lot about this

@DigitalBrainJS
Copy link
Collaborator

@theVJagrawal Before starting work on a fix, it would be a good idea to make sure that the problem really exists in the current version and is not fixed in #5316, which will be released in the next minor version.

@jimmywarting
Copy link

Dose this work?

const {data} = await oAuthClient.post(url, new UrlSearchParams({
  client_id: clientId,
  client_secret: clientSecret,
  grant_type: 'client_credentials',
  scope: scope
}))

@leaumar
Copy link
Author

leaumar commented Jan 31, 2023

@jimmywarting that does actually seem to work, thanks. We were migrating from got and were under the impression these params would stay as they were. It might well be user error to be honest, we're not experienced with axios and didn't research it very deeply.

@jimmywarting
Copy link

jimmywarting commented Jan 31, 2023

Good, Most of the http libraries out there supports encoding and understand how to serialize URLSearchParams, FormData, Blob & Files bodies and setting appropriate headers accordingly

Guess this can be closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants