Problem with Token Exchange Endpoint

Hi All,

Im trying to implement a c++ app in order to create multiple tasks when we start a project. I’ve faced a lot of problems with te comunication between my app and Asana’s API (Most of all because of my lack of knowledge). But the thing is going on.

My app succesfully conects with the API. I have a server who asks user for authentication and stores his code in the database. After that, I have implemented an User Authorization Endpoint who is able to change that code for an Asana token in order to make requests. This token, acording to the documentation, is valid for 1 hour.

My problem here is that im unable to make a functional POST to the Token Exchange Endpoint. Asana always responds the same thing:

POST’s Answer:
“{\n "error": "invalid_grant",\n "error_uri": "Build an app with Asana”,\n "error_description": "The code provided was invalid."\n}"

My code is the same as User Authorization Endpoint, wichs works pretty well (I only get error if I use the code 2 times in the same request).

Other questions:
-The code that Asana gives to the user is only valid for 15 minutes? If I dont ask for a token in that time, Do I (My users) have to ask for authotization again?

Regards, an thank you so much.

Dani.

About the other question, you can ask for a refresh token to use everytime your token expires, so you can get a new token.
@Diakoptis is great with auth problem if I remember well, Mister D. help please :slight_smile:

Bastien
Asana Certified Pro, consultant, author and developer

Hi Bastien,

Thanks for the reply.

So, once an user is authorized (He gets a code and change it for a token), Is he able to work forever making calls to the Token Exchange Endpoint?

I mean, for example, my user leaves the app and continues with his work next day. As I have understood, there is no need to grant authorization again, just making an exchange request will allow my app to keep working with Asana?

Thank you very much!

Hope @Diakoptis could give me some light to my auth problem.

You want to be passing to the Token Exchange Endpoint the refresh token that you got back from Asana. It sounds like you’re instead passing the initial code you got?

Once you’ve got an access token, you can make calls for about an hour with it. At some point around then, calls will fail with “Unauthorized”, at which point you again pass the refresh token to the Token Exchange Endpoint to get a new access token good for about another hour. The user will never have to re-authorize your app once they perform the initial authorization.

1 Like

Hi Phil,

I’ve checked my code, since the error message is the same as when I try to make two requests for a token using the same code. The thing is, im using the token instead of the initial code.

Here is my functional request for a token using initial code:

//URL: https://app.asana.com/-/oauth_token
      //Parameters of the request URL
        postData.addQueryItem("grant_type", "authorization_code");
        postData.addQueryItem("client_id", CLIENT_ID);
        postData.addQueryItem("client_secret", CLIENT_SECRET);
        postData.addQueryItem("redirect_uri", "https%3A%2F%2F192.168.65.6%3A12555%2Fasana%2Ftoken%2F");
        postData.addQueryItem("code", code); //Stored in database FE: 0/453abaaaaaaa12e8eda7

This works well and Asana gives me the token valid for one hour (Much longer than the code).

My code for the exchange request is almost the same:

//URL: https://app.asana.com/-/oauth_token
//Parameters
    refresh->postData.addQueryItem("grant_type", "refresh_token");
    refresh->postData.addQueryItem("client_id", CLIENT_ID);
    refresh->postData.addQueryItem("client_secret", CLIENT_SECRET);
    refresh->postData.addQueryItem("redirect_uri", "https%3A%2F%2F192.168.65.6%3A12555%2Fasana%2Ftoken%2F");
    refresh->postData.addQueryItem("refresh_token", old_asana_token);
//For Example: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoaaaaaaaaaaaaaaajoxNTM2NTY5ODkzfQ.ADmRU9a3ERBqCRs1h6pViw0ktbFr2Jt3bXe-NnBT4k4

But this code gives me the error from above.

Im still thinking that its a problem of my use of addQueryItem class and I’m still giving a review, but it should works…

Thank you very much.

Maybe have a look at Get refresh token I was struggling myself recently. Also I anonymised your token in your post

If you’re saying that you’re passing the token starting with “ey” as old_asana_token, then there’s your problem - you need to pass the refresh token which is the 0/453abaaaaaaa12e8eda7 value, not pass the former auth token which is the “ey” string.

2 Likes

Hey,

I’m sorry for the late response and for the answer’s context because I am with a dead laptop and I have to use my phone for this.

It seems that you don’t use the correct endpoint to get an access token providing a refresh token.

When the you authenticate the user you use the code to get an access token (valid for an hour). In the same response you have access to a refresh token (valid for years).

If you make a request and you get a validity access token error you can use the refresh token endpoint using the refresh token and you will get at the response a new access token that is valid for 1 hour.

I am not able to provide a more detailed answer with example code now, but I am sure that the forum has already threads that cover the oauth2 process and the documentation is really detailed on that.

If you don’t find a solution till tomorrow I will be back with my fixed laptop. Hopefully.

D.

1 Like

Hi All!!!

Thanks for all help!! The thing was… Im just so DUMB!!

I was confuse about the access_token with the refresh_token thinking it was the same thing. Then I thought that the initial code was the same as refresh_token… The problem was that I didn’t read the whole answer of my authorization request, here it goes:

La respuesta del POST es:  "{\n  \"access_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRob3JpemF0aW9uIjo3MjM1ODMyMjM4OTYxMzEsInNjb3BlIjoiZGVmYXVsdCBpZGVudGl0eSIsImlhdCI6MTUzNjczODExNCwiZXhwIjoxNTM2NzQxNzE0fQ.Hm_f8xn2jqY5vSQyL-V3tl2egjzOdlGhpAEX2ZaErRc\",\n  \"token_type\": \"bearer\",\n  \"expires_in\": 3600,\n  \"data\": {\n    \"id\": SECRET,\n    \"gid\": \"TOPSECRET\",\n    \"name\": \"Daniel Izquierdo\",\n    \"email\": \"blahblah@blah.com\"\n  },\n  \"refresh_token\": \"0/8258Refresh****tokennotsameASInitialCODE\"\n}"  

Im going to make an exchange request but im sure it will works!!!

Regards!!!

Dani.

2 Likes

You are not dumb at all. I implemented OAuth a couple of times, and I am always confused :sweat_smile:

Hi Guys,

That was… disappointing…

I’ve made a re-authorization request for my app just to make sure I’m doing it OK. On the first call to “-/oauth_authorize”, I recive the first code from my server:

https://192.168.65.6:12555/asana/token/?code=0%2F9cbeANDMOREDIGITS&state=ok

I store this code in my database, and I use it to get my first access_token and my refresh_token calling to “-/oauth_token” with it:

    postData.addQueryItem("grant_type", "authorization_code");
    postData.addQueryItem("client_id", CLIENT_ID);
    postData.addQueryItem("client_secret", CLIENT_SECRET);
    postData.addQueryItem("redirect_uri", "https%3A%2F%2F192.168.65.6%3A12555%2Fasana%2Ftoken%2F");
    postData.addQueryItem("code", code); //Stored in database FE: 0/7934c_AND_MORE_CHARACTERS

This POST gives me all I need to work with asana for 1 hour:

"{
\"access_token\": \"eyJ0eXAiOiJKV1QiLC_AND_A_VERY_LARGE_STRING_OF_CHARACTERS\",
\"token_type\": \"bearer\",
\"expires_in\": 3600,
\"data\": {
	\"id\": 691_MORE_NUMBERS,
	\"gid\": \"691_MORE_NUMBERS\",
	\"name\": \"Daniel Izquierdo\",
	\"email\": \"blah.blah@blah.com\"
},
\"refresh_token\": \"0/6273_DEFINITELY_NOT_SAME_AS_CODE_0/7934c...\"
}" 

Thanks to your previous help, I realized that refresh_token is the one I must use to change for a new token (I was using initial code, or the large acces_token instead).

Now, I just want to get another access_token, using my refresh_token:

refresh->postData.addQueryItem("grant_type", "refresh_token");
refresh->postData.addQueryItem("client_id", CLIENT_ID);
refresh->postData.addQueryItem("client_secret", CLIENT_SECRET);
refresh->postData.addQueryItem("redirect_uri", "https%3A%2F%2F192.168.65.6%3A12555%2Fasana%2Ftoken%2F");
refresh->postData.addQueryItem("refresh_token", "0/6273_DEFINITELY_NOT_SAME_AS_CODE_0/7934c...");

But, Aasana doesen’t want to give me my token!:

"{
\"error\": \"invalid_grant\",
\"error_uri\": \"https://asana.com/developers/documentation/getting-started/authentication\",
\"error_description\": \"The `code` provided has already been used.\"
}" 

What the am I doing wrong? Do I have to wait for an hour in order to ask for a new one?

I’ve also tried the request via URL:

### Error

No route found

https://app.asana.com/-/oauth_token?grant_type=refresh_token&client_id=NUMBER&client_secret=LARGE_NUMBER_LETTERS&redirect_uri=https%3A%2F%2F192.168.65.6%3A12555%2Fasana%2Ftoken%2F&refresh_token=0/6273_DEFINITELY_NOT_SAME_AS_CODE_0

:frowning:

Regards.

Dani.

I’ve used code today and it gives me same message “Code already used”… so its not a “timing” problem…

What you’ve posted looks right to me, not sure why it’s giving you that response. Are you SURE you’re sending the refresh token and not the initial code?

There’s no reason to even store the initial code in your database, I would remove that - you cannot and never will use it again so why store it?

1 Like

Hi Phil,

Yeah, pretty much… Im debugging every single step on my code, and one of them shows me the url structure and the code that my function is using at that moment… this is the output:

Username of getRefreshToken():  daniziz
Refresh token obtained:  "0/6273f__________"
POST's URL:  "https://app.asana.com/-/oauth_token"
URL's Query Parameters: "grant_type=refresh_token&client_id=CLIENT_ID&client_secret=CLIENT_SECRET2&redirect_uri=https%3A%2F%2F192.168.65.6%3A12555%2Fasana%2Ftoken%2F&refresh_token=0/6273________" 

I stored the code because at the begining i thought it was also the refresh_token, I have to make some changes in my code but it is the first of the list to remove it…

Regards.

Hmmm, I’m afraid I’m stumped. Maybe the Asana API guys have an idea of what’s going on. @Joe_Trollo, @Matt_Bramlage, @Jeff_Schneider?

Hi Phil,

My POST finally works!!

I didn’t cleared well my http object (The one I use for requests) and code was garbage!!

My print was showing me my variable, not the part of the object I was sending to Asana!

Thank you all for the help!

Regards,

Daniel,

2 Likes