bad request when getting access token from authorization code

837 views
Skip to first unread message

Cyrus Adkisson

unread,
Nov 6, 2013, 2:25:55 AM11/6/13
to chromium-...@chromium.org
I was developing a chrome extension earlier this year and just picked it back up tonight. Naturally, I've had to put a lot of the pillars back into place to make the thing work and actually did pretty well, until I got stuck.

My extension allows people to login with google. To this end, I have a google app registered for API access and a login button within the extension's overlay pane. When I click on it, my web services backend is able to generate a code, but then receives "Bad Request" when attempting to turn that code into an access token via a POST to https://accounts.google.com/o/oauth2/token.

This page https://developers.google.com/accounts/docs/OAuth2WebServer has instructions which I used before (and were working). Of particular interest is the step in question: 

POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code
My backend, written in Java, mimics this. Just before the request is sent (generating the ClientProtocolException Bad Request), I have my code printing out the HttpPost body:

code=4%2FgagcQkdnAoW9sFoll_GbzwZAbklf.EmblahblahblahblahbHFYhAI&client_id=205434384707-n5m763hklublahblahblabhblaho8h.apps.googleusercontent.com&client_secret=HIDDEN&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&grant_type=authorization_code

... which looks fine to me. And keep in mind, this all was working when I left it in February. 

So has something changed? Does anything about my /token targetted postbody look odd? How can I get more information other than just "Bad Request" to help troubleshoot?

Thanks for any help you might be able to provide.

Cyrus

Michael Courage

unread,
Nov 6, 2013, 2:10:54 PM11/6/13
to Cyrus Adkisson, Chromium-extensions
Are you doing a web server flow or an out-of-band installed app flow? The instructions you linked are for the former, but the redirect URI in your post is for the latter. I suspect that the client ID you are using is set up in the cloud console for the server flow and that the request is failing because of the redirect_uri mismatch.

The fix depends on what you're trying to accomplish. If you're trying to get a refresh token for your back end, the answer is probably to set up a redirect_uri on your server, and have the token sent there. If you only need access tokens for your extension, and the user will be signed into Chrome, then you can use the Identity API. For both of those (or any other OAuth flow), you need to make sure the configuration of your client ID in the console matches the flow you are implementing.


--
You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To post to this group, send email to chromium-...@chromium.org.
Visit this group at http://groups.google.com/a/chromium.org/group/chromium-extensions/.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/374a3b0e-7e00-4ad9-9147-b8344ee16ee3%40chromium.org.
For more options, visit https://groups.google.com/a/chromium.org/groups/opt_out.

Cyrus Adkisson

unread,
Nov 6, 2013, 8:51:59 PM11/6/13
to chromium-...@chromium.org, Cyrus Adkisson, cou...@chromium.org
Thank you for your reply. I appreciate it.

What I'm trying to accomplish is an out-of-band flow. The chrome extension grabs the authorization code from the initial request and passes it to the backend which attempts to make the POST request to accounts.google.com/o/oauth2/token and get an access token. I know the extension is grabbing the authorization code correctly for two reasons: 1) The extension does a javascript.alert() to show it to me and 2) the java backend prints it out in the tomcat log before attempting the POST request. (see below)

In cloud console -> project -> registered app -> myapp, I saw that the app in question was listed as a "Chrome" app, which I don't think is correct as there was no return URI listed and I believe to be an erroneous remnant from the previous interface (before Cloud Console). 

So, I created a second registered app and listed it as "other". Its details page now shows an application id, a secret and lists urn:ietf:wg:oauth:2.0:oob and http://localhost/ as the redirect URIs. My hope was that using this new app information would allow the code-for-token exchange to proceed.

No luck. Same ClientProtocolException Bad Request as before. 

The HTML encoded body of the request (using the new client id and secret) is as follows: 

code=4%2FL8-Krblahblahblahblahbzs.sblahblahblabhDn_6y0ZblahblahbhAI&
client_secret=HIDDEN&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
grant_type=authorization_code

And that all looks correct to me, yet "Bad Request" still happens. How can I get more information about what is wrong with my request? That would help out a ton.

Cyrus

p.s. Keep in mind that when I left this project in February, it was working fine. So maybe that information helps. Has something about the Oauth flow changed in the meantime I'm not aware of?


On Wednesday, November 6, 2013 2:10:54 PM UTC-5, Michael Courage wrote:
Are you doing a web server flow or an out-of-band installed app flow? The instructions you linked are for the former, but the redirect URI in your post is for the latter. I suspect that the client ID you are using is set up in the cloud console for the server flow and that the request is failing because of the redirect_uri mismatch.

The fix depends on what you're trying to accomplish. If you're trying to get a refresh token for your back end, the answer is probably to set up a redirect_uri on your server, and have the token sent there. If you only need access tokens for your extension, and the user will be signed into Chrome, then you can use the Identity API. For both of those (or any other OAuth flow), you need to make sure the configuration of your client ID in the console matches the flow you are implementing.
On Tue, Nov 5, 2013 at 11:25 PM, Cyrus Adkisson <cyru...@gmail.com> wrote:
I was developing a chrome extension earlier this year and just picked it back up tonight. Naturally, I've had to put a lot of the pillars back into place to make the thing work and actually did pretty well, until I got stuck.

My extension allows people to login with google. To this end, I have a google app registered for API access and a login button within the extension's overlay pane. When I click on it, my web services backend is able to generate a code, but then receives "Bad Request" when attempting to turn that code into an access token via a POST to https://accounts.google.com/o/oauth2/token.

This page https://developers.google.com/accounts/docs/OAuth2WebServer has instructions which I used before (and were working). Of particular interest is the step in question: 

POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code
My backend, written in Java, mimics this. Just before the request is sent (generating the ClientProtocolException Bad Request), I have my code printing out the HttpPost body:

code=4%2FgagcQkdnAoW9sFoll_GbzwZAbklf.EmblahblahblahblahbHFYhAI&client_id=205434384707-n5m763hklublahblahblabhblaho8h.apps.googleusercontent.com&client_secret=HIDDEN&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&grant_type=authorization_code

... which looks fine to me. And keep in mind, this all was working when I left it in February. 

So has something changed? Does anything about my /token targetted postbody look odd? How can I get more information other than just "Bad Request" to help troubleshoot?

Thanks for any help you might be able to provide.

Cyrus

--
You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extensions+unsub...@chromium.org.

Michael Courage

unread,
Nov 7, 2013, 2:20:53 PM11/7/13
to Cyrus Adkisson, Chromium-extensions, Michael Courage
Your request parameters look ok to me. I don't know of anything that would have changed since February. 

Do you get an error string in the response body from /o/oauth2/token? The error strings are not very verbose, but sometimes they give a hint.

It might be worthwhile to try doing the flow manually using curl if you haven't tried that already. Type the /o/oauth2/auth URL into the omnibox manually, grab the code and then:

curl -v -d '<token-request-body' -H 'Content-Type: application/x-www-form-urlencoded' 'https://accounts.google.com/o/oauth2/token'

I usually find this to be a quicker and easier way to debug OAuth2 configuration and parameter problems than debugging inside an app.

Cyrus Adkisson

unread,
Nov 10, 2013, 10:51:13 PM11/10/13
to chromium-...@chromium.org, Cyrus Adkisson, Michael Courage
I appreciate your continued responses. I was just about to write a very frustrated response explaining how I still couldn't get it working... and then I got it working.

At issue was the application id supplied to the original authorization code request. My front-end js file still contained the "old" app id (which DID change sometime in the last 9 months). 


changed to 


I had changed this value in my backend, but the frontend was still using it to get the original auth code, causing the subsequent request for token to fail. 

It should also be noted that my original "registered app" of type "Chrome" is what eventually worked. I had created a new registered app of type "native" but couldn't get it it to proceed past "pending authorization".

To tie it all up in a nice bow:

Auth code request:

     'redirect_uri=urn:ietf:wg:oauth:2.0:oob&' +

Exchange of code for access token:

nameValuePairs.add(new BasicNameValuePair("code", authorization_code)); <-- code extracted from the step above
nameValuePairs.add(new BasicNameValuePair("client_id", client_id)); <-- same id as above
nameValuePairs.add(new BasicNameValuePair("client_secret", client_secret)); 
nameValuePairs.add(new BasicNameValuePair("redirect_uri", "urn:ietf:wg:oauth:2.0:oob")); <-- this worked, despite not being listed in this "registered app"'s profile page
nameValuePairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extensions+unsubscribe...@chromium.org.

Michael Courage

unread,
Nov 11, 2013, 6:48:42 PM11/11/13
to Cyrus Adkisson, Chromium-extensions, Michael Courage
Cool, glad you got it working! Thanks for the summary of the solution too.

(I'm not sure why there's a difference between your client IDs for "native" vs. "chrome". Both types work for me.)
Reply all
Reply to author
Forward
0 new messages