Jump to content
marcin

Indy HttpClient send JSON to https://login.microsoftonline.com/

Recommended Posts

Hi Guys

 

I need a little help here

 

I'm trying to send following JSON to https://login.microsoftonline.com/

 

{
    "grant_type": "client_credentials",
    "client_id": "xxx",
    "client_secret": "_xxx_",
    "scope": "https://graph.microsoft.com/.default"
}

 

using following code:


 

IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
url := 'https://login.microsoftonline.com/' + TenantID + '/oauth2/v2.0/token';
FLastResult := IdHTTP.Post (url, requestBody);

where requestBody is  a TStream containing the string with the JSON.

 

I got "400" error response from microsoft saying that "The request body must contain the following parameter: 'grant_type'"

Apparently I'm missing something here, since I've tested this with Postman I there I get proper response containing requested token.

 

Any clues?

 

TIA

Marcin

 

 

Share this post


Link to post

Can you show a bit more code? How do you setup the stream? Perhaps you need to (re)set the position of the stream to 0 before sending.

Share this post


Link to post

I think you do not need to send JSON, take a look here: https://learn.microsoft.com/en-us/graph/auth-v2-user#3-get-a-token

 

We do this (found on the internet), it's for TRestclient, but you can see how the body is composed :


    url := TURI.Create('http://localhost');
    url.AddParameter('grant_type', 'refresh_token');
    url.AddParameter('refresh_token', RefreshToken);
    url.AddParameter('client_id', ClientID);
    url.AddParameter('client_secret', ClientSecret);
    paramBody := LRequest.Params.AddItem;
    paramBody.Value := url.Query;
    paramBody.Kind := pkREQUESTBODY;
    paramBody.Options := [poDoNotEncode];
    paramBody.ContentType := TRESTContentType.ctAPPLICATION_X_WWW_FORM_URLENCODED;

 

Edited by mvanrijnen

Share this post


Link to post
1 hour ago, omnibrain said:

Can you show a bit more code? How do you setup the stream? Perhaps you need to (re)set the position of the stream to 0 before sending.

Last version is:

 

 StringWriter := TStringWriter.Create();
 Writer := TJsonTextWriter.Create(StringWriter);
 Writer.Formatting := TJsonFormatting.Indented;
 Writer.WriteStartObject;
 Writer.WritePropertyName('grant_type');
 Writer.WriteValue('client_credentials');
 Writer.WritePropertyName('client_id');
 Writer.WriteValue(ClientID);
 Writer.WritePropertyName('client_secret');
 Writer.WriteValue(ClientSecret);
 Writer.WritePropertyName('scope');
 Writer.WriteValue('https://graph.microsoft.com/.default');
 Writer.WriteEndObject;
 requestBody := TStringStream.Create(StringWriter.ToString, TEncoding.UTF8);
 requestBody.Position := 0;

and presented JSON comes from:

 

TStringStream(RequestBody).DataString

 

Share this post


Link to post
// 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=11111111-1111-1111-1111-111111111111
&scope=user.read%20mail.read
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=jXoM3iz...    // NOTE: Only required for web apps

No JSON 

Edited by mvanrijnen

Share this post


Link to post
7 hours ago, marcin said:

I'm trying to send following JSON to https://login.microsoftonline.com/

Why are you trying to send JSON?  That is not what Microsoft's documentation tells you to send:

 

https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#redeem-a-code-for-an-access-token

 

The body is NOT to be JSON at all.  It needs to be a '&'-delimited list of 'name=value' pairs instead.

Quote

IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
url := 'https://login.microsoftonline.com/' + TenantID + '/oauth2/v2.0/token';
FLastResult := IdHTTP.Post (url, requestBody);

where requestBody is  a TStream containing the string with the JSON.

The TIdHTTP.Post() method handles the 'application/x-www-form-urlencoded' format for you, but only if you give it a TStrings (like TStringList), not a TStream, eg:

requestBody := TStringList.Create;
requestBody.Add('grant_type=client_credentials');
requestBody.Add('client_id=xxx');
requestBody.Add('client_secret=_xxx_');
requestBody.Add('scope=https://graph.microsoft.com/.default');

url := 'https://login.microsoftonline.com/' + TenantID + '/oauth2/v2.0/token';
FLastResult := IdHTTP.Post(url, requestBody);

 

Edited by Remy Lebeau
  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×