5
votes

I am trying to request access and refresh tokens from Google using oauth2, all I am getting is a "HTTP/1.1 400 Bad Request" error.

I am using IdHTTP in Delphi XE5 with the IdSSLIOHandlerSocketOpenSSL handler. I have got my Client ID, Client Secret and API Key. I have the Authorization Code.

IdHTTP is configured:

AllowCookies = True
HandleRedirects = True
HTTPOptions.hoKeepOrigProtocol = True
HTTPOptions.hoNoProtocolErrorException = True

Everything else is default.

Is there anything I should be doing beforehand, such as authentication?

What is the relevance of the redirect_uri when creating a Win32 application?

All help will be gratefully received.

This is my code:

var  Params: TStringList;
     Resp: TStringStream;
     URI: String;
begin

     Params := TStringList.Create;
     Resp := TStringStream.Create;

     try
        URI := 'https://accounts.google.com/o/oauth2/token';

        Params.Add('client_id=' + clientID);
        Params.Add('client_secret=' + clientSecret);
        Params.Add('code=' + authCode);
        Params.Add('redirect_uri=http://localhost');
        Params.Add('grant_type=authorization_code');

        IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
        IdHTTP.Post(URI, Params, Resp);

        Memo1.Lines.LoadFromStream(Resp);
        Memo1.Lines.Insert(0, IdHTTP.ResponseText);

        finally
        FreeAndNil(Params);
        FreeAndNil(Resp);
        end;

end;

EDIT:

I changed the Accept header to a setting I found elsewhere.
I added charset=utf-8 to Content-Type.
I replaced the clientID and clientSecret.

This is what IdHTTP is sending:

POST /o/oauth2/token HTTP/1.1<br>
Content-Type: application/x-www-form-urlencoded; charset=utf-8<br>
Content-Length: 240<br>
Host: accounts.google.com<br>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<br>
Accept-Encoding: identity<br>
User-Agent: Mozilla/3.0 (compatible; Indy Library)<br>

client_id=clientID&client_secret=clientSecret&code=4%2FtmTyuvpcSMIkoyJcFmicfXQEDpYiw_QilkO2dXv_nUc&redirect_uri=http%3A%2F%2Flocalhost&grant_type=authorization_code

2
The code should work. Some parameter has to be wrong. Note that the redirect_uri has to exactly match to previous request and value in API settings.smooty86
@smooty86 I downloaded the Client_ID from the Google Developers Console in JSON and there were 2 Redirects in there: "urn:ietf:wg:oauth:2.0:oob","h t t p://localhost"Alan Finch
Btw. you are not supposed to set ContentType. Indy does that. You should also probably check the error message returned from google. Use try/except for the Post, catch the exception and get error message using "(E as EIdHTTPProtocolException).ErrorMessage"smooty86
If I try Indy again that may be helpful. Why does Indy have to use Exceptions so much? Why can't it just return the error as the return code and put the content in the content? This is how Synapse works and was so much easier to debug.Alan Finch
@smooty86 Just as a side note. Thanks for your feedback, your help is appreciated.Alan Finch

2 Answers

3
votes

I solved it!

Indy was the problem.

I used synapse 4.0 components instead and had it working within 10 mins.

That's a day and a half I'll never get back. Thanks Indy :(

0
votes

Save yourself some headache. Get Clever Internet Suite for Delphi. Because, the shit developers don't understand that SSL HTTP client is such a basic requirement. They just keep on proposing just HTTP clients instead. Forget Indy and Synapse. I am nowhere affiliated to CIS but my 2 cents. Works flawlessly with my XE5.