Hi team!
I trying to add mechanizm to refresh
access_token
by passing
refresh_token
but unfortunately I’m getting an error:
“The
refresh_token
parameter was missing.”
with 400 HTTP code.
Those are steps which I’m did - can someone verify it and tell me if I did something wrong or something stopped working after recent changes
Changes to API token formats
?
Obtain initial access by code exchange:
POST https://app.asana.com/-/oauth_token
?grant_type=authorization_code
&client_id=1234567890
&client_secret=client_secret_123
&redirect_uri=https://my-redirect-uri.com
&code=2/code
HTTP/1.1
response which I got:
HTTP/1.1 200
"access_token": "access_token_123"",
"token_type": "bearer",
"expires_in": 3600,
"data": {
"id": 123,
"gid": "123",
"name": "me me",
"email": "[email protected]"
"refresh_token": "2\refresh_token_123"
Obtain a new token by passing refresh token
POST https://app.asana.com/-/oauth_token
?grant_type=refresh_token
&refresh_token=2\refresh_token_123
&client_id=1234567890
&client_secret=client_secret_123
HTTP/1.1
response which I got:
HTTP/1.1 400 Bad Request
"error": "invalid_request",
"error_uri": "https:\u002F\u002Fasana.com\u002Fdevelopers\u002Fdocumentation\u002Fgetting-started\u002Fauthentication",
"error_description": "The `refresh_token` parameter was missing."
Hi @Donnie_MacEntire,
One thing I can see is you’re missing the redirect_uri
parameter in your refresh call:
Hi @Phil_Seeman! Thanks for replying!
Sorry, I was trying all possible combinations and by mistake I added a one w/o redirect_uri but also when I’m adding it I’m getting this error.
What is quite interesting, when I removed ‘client_secret’ I got an different error:
"error": "invalid_grant",
"error_uri": "https:\u002F\u002Fasana.com\u002Fdevelopers\u002Fdocumentation\u002Fgetting-started\u002Fauthentication",
"error_description": "The `refresh_token` provided was invalid."
Hi @Donnie_MacEntire,
Are you sending your request in a “form-encoded POST
body” (OAuth)?
Here’s a template cURL command that makes this request with a form-encoded POST body:
Example Request:
curl --location 'https://app.asana.com/-/oauth_token' \
--form 'grant_type="refresh_token"' \
--form 'refresh_token="<YOUR_REFRESH_TOKEN>"' \
--form 'client_id="<YOUR_CLIENT_ID>"' \
--form 'client_secret="<YOUR_CLIENT_SECRET>"' \
--form 'redirect_uri="<YOUR_REDIRECT_URI>"'
Example Response:
"access_token": "<ACCESS_TOKEN>",
"token_type": "bearer",
"expires_in": 3600,
"data": {
"id": 123,
"gid": "456",
"name": "John",
"email": "[email protected]"
Here’s how I tested:
Set up an ran this example oauth app node-oauth-demo
Open up the app in my browser (i.e., went to http://localhost:3000/ → clicks on the “Authenticate with Asana” button)
Look at the output in the console and take note of the refresh_token
***** Response from the token exchange request:
access_token: '123456789',
token_type: 'bearer',
expires_in: 3600,
data: {
id: 123,
gid: '456',
name: 'John',
email: '[email protected]'
refresh_token: '2/120'
Went into Postman → “Body” tab → “form-data” radio button → fill out the information for grant_type
, client_id
, ‘client_secret’, refresh_token
, redirect_uri
. Click on “Send” button and see results.
NOTE: although we say redirect_uri
is required in our docs I tested this without passing in a redirect_uri
and the request still succeeds. I believe the required redirect_uri
is meant for the POST https://app.asana.com/-/oauth_authorize
request not the POST https://app.asana.com/-/oauth_token
endpoint
Hi John!
thanks for your help! now I now why it’s not working 
but… it’s totally misleading!
in a single endpoint once you expect “x-www-form-urlencoded” for code exchange and for refreshing you expect “form-data”

also in the docs, and here you mentioning “form-encoded POST body” which isn’t specific enough… even ChatGPT would fall in to the same problem like me 
me > which header I should use form-data or x-www-form-urlencoded when docs says form-encoded?
chatgpt 3.5 > If the API documentation specifies “form-encoded” without explicitly mentioning either form-data
or x-www-form-urlencoded
, it might be a bit ambiguous. However, in many cases, “form-encoded” refers to x-www-form-urlencoded
can you maybe at least update the docs to be more specific? 
Hi @Donnie_MacEntire,
Thank you for your feedback. I can update the docs to be more clear. For context both options work:
Content-Type: application/x-www-form-urlencoded
Content-Type: multipart/form-data;boundary="boundary"
In my previous reply, I shared a screenshot using form-data
here’s a screenshot of making that request using x-www-form-urlencoded
in Postman:
Here’s what the cURL looks like for making a request with x-www-form-urlencoded
:
curl --location 'https://app.asana.com/-/oauth_token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=<YOUR_REFRESH_TOKEN>' \
--data-urlencode 'client_id=<YOUR_CLIENT_ID>' \
--data-urlencode 'client_secret=<YOUR_CLIENT_SECRET>'
Looking through some posts on Stack Overflow it looks like the key difference between x-www-form-urlencoded
and form-data
is that:
Content-Type: application/x-www-form-urlencoded
:
Use this for simple text/ ASCII data
Used more generally to send text data to the server
Content-Type: multipart/form-data;boundary="boundary"
Use this for non-ASCII text or large binary data
Used to send binary data, most notably for uploading files to the server
Sources:
Postman Chrome: What is the difference between form-data, x-www-form-urlencoded and raw
application/x-www-form-urlencoded or multipart/form-data?
Difference between application/x-www-form-urlencoded and multipart/form-data in HTTP/HTML?
Going from what we learned above, it seems like application/x-www-form-urlencoded
is sufficient on making the request.
Applying this learning to our Upload an attachment endpoint it makes sense why this endpoint requires multipart/form-data
since this endpoint can take in binary data from an attachment.