[Consume REST API] Parameters not send in the body HTTP 400 Bad Request

I am consuming the Microsoft Azure AD token Rest API

https://login.microsoftonline.com/[tenantid]/oauth2/v2.0/token

When I test the API in Service Studio I get a bearer token response:

But when I call it from a server action I get at HTTP 400 bad request.

I increased the loglevel for this REST API.

In ServiceCenter I see that the content length of the request = 0:

This is the output of the HTTP trace:

POST https://login.microsoftonline.com/[tenant id]/oauth2/v2.0/token HTTP/1.1
User-Agent: OutSystemsPlatform
Content-Type: application/x-www-form-urlencoded
Host: login.microsoftonline.com
Content-Length: 0



HTTP/1.1 400 Bad Request
Pragma: no-cache
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
x-ms-request-id: 8f7fa9f6-9c8a-4bb2-b972-92acc2a15400
x-ms-ests-server: 2.1.10681.8 - AMS2 ProdSlices
Cache-Control: no-cache, no-store
Content-Type: application/json; charset=utf-8
Expires: -1
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
Set-Cookie: fpc=AobEy9qs9ZxEnDOo5xjeWLo; expires=Thu, 09-Jul-2020 05:52:51 GMT; path=/; secure; HttpOnly; SameSite=None,x-ms-gateway-slice=prod; path=/; SameSite=None; secure; HttpOnly,stsservicecookie=ests; path=/; SameSite=None; secure; HttpOnly
Date: Tue, 09 Jun 2020 05:52:50 GMT
Content-Length: 503

{"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: 8f7fa9f6-9c8a-4bb2-b972-92acc2a15400\r\nCorrelation ID: 2fbefec9-b426-4d24-b45f-fb8ad55c5517\r\nTimestamp: 2020-06-09 05:52:51Z","error_codes":[900144],"timestamp":"2020-06-09 05:52:51Z","trace_id":"8f7fa9f6-9c8a-4bb2-b972-92acc2a15400","correlation_id":"2fbefec9-b426-4d24-b45f-fb8ad55c5517","error_uri":"https://login.microsoftonline.com/error?code=900144"}

Finally I also followed the solution with the OnBeforeRequest from this post:

https://www.outsystems.com/forums/discussion/43043/consume-rest-api-sending-parameters-in-body/

but this does not seem to help.

Any suggestions about what I am doing wrong?

Hi Raymond,

Did you set the Receive In property to Body of the paramters?

Regards,

Daniel

Hi Daniel !

The Send In property is set to Body for all input parameters.

Hi Raymond,

Can you share your module(s)? 

I created a REST Service with inputs in the body. Then in another module, I consume it and can receive them without problems.

Regards,

Daniel

Hereby the 2 OML files.

Webscreen TestAzureAPI with a button 'Test' performing screen action DoItOnAzure.

The screenaction calls the server action GetAppRole in the other OML file.

In Azure I created a App registration with sufficient rights.

Unfortunately the first step PostToken fails with a HTTP 400 error.

2nd OML

Hi Raymond,

Why you have this content type on the 

On the original GetToken method in MicrosoftLoginConnector this is:


I cannot test your module as it is missing dependencies. But my advice would be to deviate as little as possible to the (working) implementation of the MicrosoftLoginConnector.

Regards,

Daniel

I changed the content type because Postman is using this and it was a wild guess this could be the problem. But if you look at the HTTP trace you can see OutSystems overwrites it to your value.

In Postman the same rest api only works if I put the keys in the body as form-data

When you look at the generated HTTP code it shows the parameter are put in as form-data. That is a difference. 

POST /***********hidden********************/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
User-Agent: PostmanRuntime/7.22.0
Accept: */*
Cache-Control: no-cache
Postman-Token: bbd22a0e-f261-4c33-98fb-1646a5a3d5b2
Host: login.microsoftonline.com
Accept-Encoding: gzip, deflate, br
Cookie: x-ms-gateway-slice=prod; stsservicecookie=ests; fpc=AirWaZ1jPRtCh9mEiGjPSA7r6MazAgAAALErcNYOAAAA
Content-Length: 613
Connection: keep-alive

----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="client_id"

************************hidden******************************
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="scope"

https://graph.microsoft.com/.default
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="client_secret"

************************hidden*****************************
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="grant_type"

client_credentials
----WebKitFormBoundary7MA4YWxkTrZu0gW

Looking at the MicrosoftLoginConnector I don't see any differences in getting the token beside the MicrosoftLoginConnector is for endusers so it uses the grant_type=authorization_code and I am using an application account with client_credentials. See: https://docs.microsoft.com/en-us/rest/api/azure/#create-the-request


But still I find it strange that testing the REST Api in Service Studio works fine but using it runtime it fails.....

If it works in SS and not at run time, then check in Service Center the effective values for credentials, etc.

In Service Center I only see this in the error log:

The integration log is not showing any credentials. Where can I find them?

Solution

Ok Daniel I did a replublish of the enduser module because in Service Center I saw a warning "This Module has outdated references. You should publish it to avoid running outdated code." After this and changing the content-type back to 

SyntaxEditor Code Snippet

"application/x-www-form-urlencoded"

It works, thanks for your help !

Solution