marcin 0 Posted November 14, 2022 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
omnibrain 15 Posted November 14, 2022 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
mvanrijnen 123 Posted November 14, 2022 (edited) 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 November 14, 2022 by mvanrijnen Share this post Link to post
marcin 0 Posted November 14, 2022 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
mvanrijnen 123 Posted November 14, 2022 (edited) // 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 November 14, 2022 by mvanrijnen Share this post Link to post
Remy Lebeau 1396 Posted November 14, 2022 (edited) 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 November 14, 2022 by Remy Lebeau 1 Share this post Link to post
marcin 0 Posted November 15, 2022 @Remy Lebeau You are the (rock) star 😃, thank you so much It looks like looong learning path ahead of me Share this post Link to post
mvanrijnen 123 Posted November 15, 2022 Glad Remy made it clear for you not to send JSON. I totally forgot about that 😉 Share this post Link to post