Issue requesting an access token

562 views
Skip to first unread message

stephe...@gmail.com

unread,
Dec 15, 2012, 7:41:52 PM12/15/12
to im...@googlegroups.com
After getting an authorization code at my callback URL, I attempt to fetch an access token:

curl -X POST -H "Authorization: Client-ID $client_id" -H "Content-Type: application/json; charset=utf-8" https://api.imgur.com/oauth2/token -d "{"refresh_token":"$authorization_code","client_id":"$client_id","client_secret":"$client_secret","grant_type":"refresh_token"}"

I get this as the response:

{"data":{"access_token":null,"expires":-1355617767,"account_username":null},"success":true,"status":200}

It seems to be a successful response, but the access token and username are null, and the expires doesn't quite seem right.

Am I missing something? I can't use the authorization code itself as a Bearer token (I get 403s).

Thanks,
Stephen

Matthew Harris

unread,
Dec 16, 2012, 12:40:22 PM12/16/12
to im...@googlegroups.com
I am seeing the same behavior as well. 

12-16 12:35:48.163: DEBUG/***.HttpConnection(2002): Setting HTTP POST request JSON:
        {"refresh_token":"*","client_id":"*","client_secret":"*","grant_type":"refresh_token"}
12-16 12:35:48.163: DEBUG/***.HttpConnection(2002): Making HTTP POST request to https://api.imgur.com/oauth2/token
12-16 12:35:48.734: DEBUG/***.HttpConnection(2002): Response JSON: {"data":{"access_token":null,"expires":-1355679348,"account_username":null},"success":true,"status":200}
12-16 12:35:48.794: DEBUG/***(2002): token recieved! null

Thanks,
Matt

stephe...@gmail.com

unread,
Dec 16, 2012, 1:35:23 PM12/16/12
to im...@googlegroups.com
For what it's worth, I get the same response with an empty body. The OAuth integration with API v2 had a lot of error messaging that made it easy to troubleshoot issues like this.

It would be helpful to have more documentation around the OAuth 2 endpoints in general. An example for the /oauth2/token endpoint, for one, and more information around using /oauth2/addclient and /oauth2/secret.

Josh@Imgur

unread,
Dec 17, 2012, 1:04:54 PM12/17/12
to im...@googlegroups.com
Hey, sorry you're having issues. In the first response from the access token you should be getting another token named refresh_token in the response. Based on the variable names in your request, I wanted to make sure you aren't sending the access_token instead of the refresh token.

I will also go in and verify everything is working and add some better error handling to prevent this in future.

~Josh

stephe...@gmail.com

unread,
Dec 17, 2012, 1:20:03 PM12/17/12
to im...@googlegroups.com
The response I'm getting at my callback/redirect URI only has the following query string: "?code=:hex digest".

It doesn't identify whether it's a refresh_token, access_token, or otherwise. When I attempt to use it as a refresh token, I get the response I posted earlier. When I attempt to use it as an access token, I get 403s.

Matthew Harris

unread,
Dec 17, 2012, 8:27:09 PM12/17/12
to im...@googlegroups.com
Any update on this Josh? 

Josh@Imgur

unread,
Dec 18, 2012, 1:40:05 PM12/18/12
to im...@googlegroups.com
We found that the issue with the auth causing part of the issue. There is a fix that should be deployed to our servers shortly.  I will let you know when the fix has been posted, but the issue has been found.  If you want to change it on your end to make it work, send POST parameters rather than JSON in the curl request.

Also at the point that you're sending request tokens your Authorization header should be set to the access token, not to the Client-ID.  By doing this you'll get a faster response from our servers because the servers have less work to do given the access_token in the header.

Josh

stephe...@gmail.com

unread,
Dec 18, 2012, 2:06:24 PM12/18/12
to im...@googlegroups.com
Hi Josh,

I actually get a 500 error when I try using POST parameters:

curl -X POST -H "Authorization: Client-ID $client_id" -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" -H "Accept-Language: en, ja, fr, de, es, it, pt, pt-PT, nl, sv, nb, da, fi, ru, pl, zh-Hans, zh-Hant, ko, ar, cs, hu, tr, th, ca, hr, el, he, ro, sk, uk, en-us" "https://api.imgur.com/oauth2/token" -d "refresh_token=$refresh_token" -d "client_id=$client_id" -d "client_secret=$client_secret" -d "grant_type=refresh_token"

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> imgur: the simple error page</title>
...

Same thing if I explicitly use "Accept: application/json; charset=utf-8"

Josh@Imgur

unread,
Dec 18, 2012, 2:39:16 PM12/18/12
to im...@googlegroups.com
The 500 errors normally occur when the site is over capacity. I just used the same curl request you posted, and it worked fine.

You may also want to verify that the refresh_token is a refresh token, otherwise it will throw that same error.  We are adding better error handling for token responses now to try and clear up a lot of the confusion that's going on with it.

~ Josh

stephe...@gmail.com

unread,
Dec 18, 2012, 2:44:57 PM12/18/12
to im...@googlegroups.com
I'm getting 500 errors every time. How do I verify that refresh_token is a refresh token?

The callback I get on my end only has the following parameter in the query string, e.g.:

?code=76388bc19b1905a402c16e9baf782cbe8b257c7f

Can't this be used as a refresh token? What am I supposed to do with a "code" that I request with "response_type=code"?

Thanks,
Stephen

stephe...@gmail.com

unread,
Dec 18, 2012, 2:46:39 PM12/18/12
to im...@googlegroups.com
Also, does over-capacity return a 500 or a 503 (or 502/4)? It would be nice to not get 500 errors in general, as they're hard to troubleshoot and usually point to an exception getting raised in server code :)

Thanks again,
Stephen

Josh@Imgur

unread,
Dec 18, 2012, 2:54:29 PM12/18/12
to im...@googlegroups.com
I agree, but a 500 makes sense for over capacity, it's our generalized error is happening.

There shouldn't be any 500's in the rest of the API, unless it's a problem with the server.  If you get a 500 error feel free to email us or post here with any questions.  We are working on removing any lingering errors like that in the OAuth2 information.

~ Josh

stephe...@gmail.com

unread,
Dec 18, 2012, 3:03:49 PM12/18/12
to im...@googlegroups.com
Sounds good. Just wanted clarity on how to handle errors on my end.

Can you please also clarify my earlier question?:

How do I verify that refresh_token is a refresh token? The callback I get on my end only has the following parameter in the query string, e.g.:

?code=76388bc19b1905a402c16e9baf782cbe8b257c7f

Can't this be used as a refresh token? What am I supposed to do with a "code" that I request with "response_type=code"?

Thanks!

Josh@Imgur

unread,
Dec 18, 2012, 3:11:05 PM12/18/12
to im...@googlegroups.com
That's the access token, if you make a GET request to https://api.imgur.com/oauth2/token you will see your access token, the refresh token, and other information about your current token.  Make sure that your request headers are setting the Authorization header to Bearer <code> though.

I will make sure that the authorization page will show the code as an access_token rather than just "code", however it's standard OAuth2 to not provide a refresh token on initial authorization.  Therefore, I will have to discuss with the team if we want to include that or not (seems like it'd make things even easier for you guys to use though!)

~ Josh

stephe...@gmail.com

unread,
Dec 18, 2012, 3:24:25 PM12/18/12
to im...@googlegroups.com
Ah, an example or explanation in your docs would help, too.

Even the GET request to /oauth2/token seems to be failing for me:

~ % curl -H "Authorization: Bearer $code" https://api.imgur.com/oauth2/token
{"data":{"access_token":null,"expires":-1355862122,"account_username":null},"success":true,"status":200}

stephe...@gmail.com

unread,
Dec 18, 2012, 3:26:57 PM12/18/12
to im...@googlegroups.com
This is what confused me in your example:

https://example.com/oauthcallback?code=AUTHORIZATION_CODE

Wherein "AUTHORIZATION_CODE" is the label, not ACCESS_TOKEN.

(Meanwhile you use ACCESS_TOKEN in your JavaScript Responses example.)

stephe...@gmail.com

unread,
Dec 18, 2012, 3:58:29 PM12/18/12
to im...@googlegroups.com
I just ended up reading the spec and have things basically working. Pertinent section:

http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.1.3

Will take some testing, but I think I finally have it.

It's a bummer that access tokens we get via authorization code expire (adds an extra layer of complexity that wasn't there with OAuth 1). I assume the refresh token changes every time I fetch a new access token, and that I'll have to re-save the refresh token every time?

Josh@Imgur

unread,
Dec 18, 2012, 4:34:44 PM12/18/12
to im...@googlegroups.com
Yeah, the refresh tokens expire after use. They also expire after a time limit as well.  The idea is that it's more secure so someone can only grab it for so long? I guess? Anyways, I think the root of your problems is your /authorization request.

When you are redirecting to our authorization page you have to set a response_type and I believe you're setting it to auth_code or code rather than token.  If it's set to token it properly generates the access_token and the refresh_token for you.

~ Josh

stephe...@gmail.com

unread,
Dec 18, 2012, 5:09:00 PM12/18/12
to im...@googlegroups.com
As far as I know, refresh tokens should _not_ expire after a time limit.

The security concern is at the access token level because acquiring a new access token requires the client_id, client_secret, and refresh_token/authorization_code. Because of this, a malicious third party cannot intercept the access_token and use it indefinitely. If a malicious third party were to intercept a refresh_token, they would not be able to get an access token unless they also managed to intercept the client_id and client_secret.

Consider my example:

I have a desktop application that used to store the OAuth 1 access token securely in the OS X login keychain. I can no longer do this with your OAuth 2 integration because you expire your access tokens. I can, however, store the refresh token and fetch access tokens as needed (updating the refresh_token as I go if need be). If an unused refresh token expires after a time limit, though, then I will have to make my users re-authorize regularly, a step that I should be able to avoid (securely, using the refresh token). I'd really like to make sure the user experience doesn't degrade.

Can I request that unused refresh tokens do not expire? If they do expire, what's the TTL? I'd hope at least a few days (I don't want an app user to go to sleep, wake up, and have to re-auth every morning they use my app).

Thanks,
Stephen

Matthew Harris

unread,
Dec 18, 2012, 9:11:22 PM12/18/12
to im...@googlegroups.com
Hey Stephen, 

Thanks for posting the draft of oauth 2.0 - you got me up and running and saved me a lot of time! 

Josh@Imgur

unread,
Dec 18, 2012, 9:59:13 PM12/18/12
to im...@googlegroups.com
Hey Stephen,

The expires for the refresh_token is currently set to two weeks.  We're discussing removing the expires time on refresh tokens now, I will keep you posted if anything changes.

~ Josh

Matthew Harris

unread,
Dec 18, 2012, 10:46:20 PM12/18/12
to im...@googlegroups.com
Stephen or anyone else seeing any issues with the auth code approach?

On my first request for an access token (using a auth code), everything works ok and I get a response like so:

{"access_token":"d9e86dbb43df4c9********c80dfc31aed6f1669","expires_in":3600,"token_type":"bearer","scope":null,"refresh_token":"16a762837b6*********173212893c7c9fb84"}

However, any subsequent request for an access token from any instance of my application fails with a imgur HTML error page response, every request I make (with NEW auth code after a user re-auths the app) for at least 20-30 minutes fails with a html error page. 

This happens on one instance of an application as well as multiple - for example...Consider my android app running on two different devices. If device 1 gets authorization from the user, the imgur oauth endpoint gives me an access token successfully. However, if device 2 gets authorization from the same user, the imgur oauth endpoint responds with a HTML error page. 

Anyone else seeing this behavior? maybe I need to RTFM...?

Josh@Imgur

unread,
Dec 19, 2012, 1:10:30 AM12/19/12
to im...@googlegroups.com
Hey Matthew,

How are you you sending the subsequent request to generate the new access token?  Can you please include the headers (remove any private data you want)?  It should be able to handle multiple instances of the same users, I was to successfully test on two different browsers which should simulate to different devices.

~ Josh

Matthew Harris

unread,
Dec 19, 2012, 10:17:09 AM12/19/12
to im...@googlegroups.com
Hey Josh,

Below are my requests the first one is successful, but any subsequent requests fail for a certain amount of time (still not sure exactly what amount that is).

12-19 09:57:59.353: INFO/ActivityManager(150): START {act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=*********-imgur://callback?code=c4dafbc1d844922cb428********* flg=0x3000000 cmp=com.v3.playground/.LoginActivity (has extras) u=0} from pid 150


12-19 09:57:59.733: DEBUG/*********.HttpConnection(1407): posting url encoded entity grant_type=authorization_code&code=c4dafbc1d844922cb428*********&redirect_url=*********-imgur%3A%2F%2Fcallback&client_id=b86d*********


12-19 09:57:59.733: DEBUG/*********.HttpConnection(1407): Making HTTP POST request to https://api.imgur.com/oauth2/token
12-19 09:57:59.833: DEBUG/*********.HttpConnection(1407): with header: Content-Type=application/x-www-form-urlencoded
12-19 09:57:59.833: DEBUG/*********.HttpConnection(1407): with header: Authorization=Client-ID b86d*********


12-19 09:58:00.443: DEBUG/*********.HttpConnection(1407): Response JSON: {"access_token":"7c3df1b030e1d60d7e8e8*********","expires_in":3600,"token_type":"bearer","scope":null,"refresh_token":"69ced1fca0f13d5a631cd0*********"}
12-19 09:58:00.643: DEBUG/*********(1407): token recieved! 7c3df1b030e1d60d7e8e8f50*********

______

Here is my second request that fails after getting a new code in a new instance of my app: 

12-19 10:00:52.723: INFO/ActivityManager(150): START {act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=*********-imgur://callback?code=0123bda1a21714b3aa3f4********* flg=0x3000000 cmp=com.v3.playground/.LoginActivity (has extras) u=0} from pid 150


12-19 10:00:53.093: DEBUG/*********.HttpConnection(1476): posting url encoded entity grant_type=authorization_code&code=0123bda1a21714b3aa3f47dc*********&redirect_url=*********-imgur%3A%2F%2Fcallback&client_id=b86d30*********


12-19 10:00:53.125: DEBUG/*********.HttpConnection(1476): Making HTTP POST request to https://api.imgur.com/oauth2/token


12-19 10:00:53.183: DEBUG/*********.HttpConnection(1476): with header: Content-Type=application/x-www-form-urlencoded
12-19 10:00:53.183: DEBUG/*********.HttpConnection(1476): with header: Authorization=Client-ID b86d3*********


12-19 10:00:53.813: DEBUG/*********.HttpConnection(1476): Response JSON: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
        <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> .....the remaining content is html error page.


Let me know if something does not look right on my end or if you need more info. 


Thanks,
Matt

mrgr...@gmail.com

unread,
Dec 19, 2012, 10:27:00 AM12/19/12
to im...@googlegroups.com
Hey Matthew,

Is there and error code on the HTML error page? That would help us track it down in the logs.

Matthew Harris

unread,
Dec 19, 2012, 10:41:58 AM12/19/12
to im...@googlegroups.com
This is what I am seeing in the html for an error code: 

        <div id="text-content">
               
<h1>Error (0)</h1>


               
<div class="textbox bigtext">
                        Sorry! There was an error (code:
<span class="green">0</span>)
                        retrieving the page you requested. Try refreshing or double checking
                        your URL. If you think this error is an error, try
                       
<a href="http://imgur.com/contact">contacting us</a> about it.
               
</div>
       
</div>

Josh@Imgur

unread,
Dec 19, 2012, 3:48:04 PM12/19/12
to im...@googlegroups.com
Hey Matthew,

It looks like you're switching between authorization codes and access tokens.  When you're doing your first post try setting the grant_type to token instead of authorization code.  When you make your second request try making the POST request to /oauth2/token with the params ...

client_id = <client_id>
client_secret = <client_secret>
response_type = token
grant_type = refresh_token
refresh_token = <refresh_token>

You will be given a refresh_token on the first request, as well as an access token.  The access token is what you will send to verify the user.

Let me know how this works for ya,
~ Josh

Matthew Harris

unread,
Dec 19, 2012, 9:04:16 PM12/19/12
to im...@googlegroups.com
What do you mean by first post? The problem I am facing is that the two requests (although exactly the same - with the exception of the auth code value) are independent from each other are getting different responses from the server. It works fine the for the first request - but stops working at all after that. 

Device 1 = User authorizes app > App gets auth code > app post code to token endpoint > token response comes back 
Device 2 = Same User authorizes app > App gets auth code > app post code to token endpoint > html error page comes back 

*also note that the same thing happens on the same request being made on the same device. Basically once I get one successful response for the code - its like 30 minutes until it works for any request again. 

After reading this article: http://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified I guess maybe I should just try the web client oauth flow and parse the tokens out of the fragment....as that seemed to be returned fine when I originally was testing that  - I just thought I was supposed to be using the authorization code flow. 

Thanks for troubleshooting with me. Do you guys think a native mobile app should be using the auth code or token oauth flow? 

Thanks for everything.

Matt

Brian

unread,
Dec 19, 2012, 9:41:59 PM12/19/12
to im...@googlegroups.com

After reading this article: http://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified ..

hmm wow.. this is really stupid, according to the article, OAuth 2.0 completely breaks the security for Desktop apps, as they are now forced to ask the user's login/password, rather than having them grant the app access through the service website as was the case with 1.0

Matthew Harris

unread,
Dec 19, 2012, 10:01:15 PM12/19/12
to im...@googlegroups.com
Yea it seems a bit off for sure...Here is how google is doing it: 

Brian

unread,
Dec 19, 2012, 10:23:47 PM12/19/12
to im...@googlegroups.com
Yeah same bs

Your application can choose to have the authorization code returned in the title of the web page or to a http://localhost port. Once the application receives the authorization code, it can exchange the code for an access token and a refresh token.

You have to either use your own website to receive the code/token or embed some BS browser page in the app (involving bloated ActiveX crap etc) to read it. Can't believe the people behind OA2 were so dumb to discard the desktop app scenario. I hope Imgur will have a workaround for this (they could easily implement a special code in the return URI to specify the user needs a PIN or similar for the app, rather than redirecting to a given URL). 
Reply all
Reply to author
Forward
0 new messages