Refresh Tokens using Python requests

latest-release October 28, 2019

I will go straight to the question. How do I refresh the bit bucket token OAuth 2.0 using python requests.

According to https://developer.atlassian.com/cloud/bitbucket/oauth-2/ this is what they recommend.

$ curl -X POST -u "client_id:secret" \
  https://bitbucket.org/site/oauth2/access_token \
  -d grant_type=refresh_token -d refresh_token={refresh_toke
n}
 Only to get this {"error_description": "Invalid refresh_token", "error": "invalid_request"}

 Mainly I want to do this in python and here is my approach

import requests
auth = ("I put real client_id here", "and-i-put-secret-here")

params={"grant_type":"refresh_token", "refresh_token":"The-token-i-want-to-refresh"}

h={"Content-type": "application/json"}

ret = requests.post(refurl, auth=auth, params=params, headers=h)
# the response is 400 and when i do


ret.content

'{"error_description": "Unsupported grant type: None", "error": "invalid_grant"}'


The same error as the curl they recommended.

The question is how do I refresh the token.

1 answer

1 accepted

0 votes
Answer accepted
Daniil Penkin
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
October 28, 2019

Hello @latest-release,

Thanks for reaching out.

Three things I can see:

  • refresh_token parameter is not really the token you want to refresh, it's the token you're refreshing an access token with. So basically when you set up OAuth 2.0 you got two tokens: access token (short-lived) and refresh token (long-lived) which you need to use here to get the new access token (and potentially new refresh token).
  • there should be no Content-Type: application/json header, as this request should have no JSON payload.
  • instead of params you should be passing parameters in data (which is what -d option does in curl) to submit them as a form.

This works fine:

import requests
auth = ("<consumer_id>", "<consumer_secret>")

params = {
"grant_type":"refresh_token",
"refresh_token":"<your_refresh_token_here>"
}

url = "https://bitbucket.org/site/oauth2/access_token"

ret = requests.post(url, auth=auth, data=params)

Hope this helps.

Cheers,
Daniil

latest-release October 29, 2019

Thanks you @Daniil Penkin  I will try out your solution and post a happy reply.

latest-release October 30, 2019

IT WORKED

nbarnwell July 23, 2020

This makes no sense. What's the point of refresh tokens if you have stored the client ID/key and secret, and can just get a new access token that way?

latest-release July 23, 2020

Your sarcastically replying to a solution that was already solved that's what makes no sense at all. You think each application has the same design storing tokens, What if tokens expire and yes they do expire, what would you do? Purge the whole app? and each token issuer has a way of refreshing or renewing.

nbarnwell July 23, 2020

There's literally no sarcasm in what I'm saying at all. I must be missing something - the idea of a refresh token is that it's a bit safer to store it on a machine than the original credentials used to obtain the access token. So if you need the original credentials to refresh an access token, you could avoid the refresh token part of things and literally just get a new access token, no?

In other words, if I have to store the client ID and client secret somewhere in order to use a refresh token, why bother with refresh tokens?

I expected to be able to call an endpoint with nothing more than the refresh token, and get a new access token and refresh token back.

Daniil Penkin
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 23, 2020

Hi @nbarnwell,

You can't get new access token with just client ID and key. You also need some user "input" unless you're after Client Credentials Grant which would create a token not for the end user but for the owner of OAuth consumer. That "input" might be the OAuth dance in the browser (e.g. a browser app, or via authorization code grant), or their credentials, or a JWT token in case it's a Connect app.

As long as you keep the refresh token, you can use just it along with client ID and secret – without any additional user input – to obtain a short-lived access token and authenticate your requests against Bitbucket.

Hope this makes sense.

Cheers,
Daniil

Daniil Penkin
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 23, 2020

In other words, if I have to store the client ID and client secret somewhere in order to use a refresh token, why bother with refresh tokens?

There are many use cases, but one of them is that a third party application, if the user gave consent beforehand, can act in the system on user's behalf without ever storing real credentials of that user and allowing the user to revoke such consent for that app to impersonate them at any time. Refresh token is a per-end-user secret that would give the app such permissions. If the user revokes their consent, refresh token expires, and no new access tokens can be obtained using it.

If the app loses refresh token, it won't be able to get a new one without "asking" the user again. There're some shortcuts there, but nevertheless the user would need to take some action.

So, client ID and secret are essentially credentials authenticating that app against Bitbucket while refresh token is a secret allowing that app to obtain access token to access data of a user (2LO) or to impersonate a user, e.g. act on their behalf (3LO).

Cheers,
Daniil

Muskan Paliwal July 6, 2023

Hey everyone, I tried the same solution as described above but it doesn't work for me. I am still getting the same error: invalid refresh token

Here is what I am trying: curl -X POST -u "client_id:client_secret" https://bitbucket.org/site/oauth2/access_token -d grant_type=_type="refresh_token" -d refresh_token={refresh_token} 
Muskan Paliwal July 17, 2023

@Danill  Penkin, I would request you to have a look at it

Daniil Penkin
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 18, 2023

Hi @Muskan Paliwal,

Well, given the error you get back from Bitbucket, the problem must be with the refresh token. Make sure you pass the right value. The `curl` command you mentioned seems ok to me.

After the initial procedure you should have received two tokens: refresh token and access token. The latter is used to make authenticated requests to Bitbucket but has a relatively short lifespan, whereas the former is long lived, and you can use it to get new refresh and access tokens.

Hope this helps.

Cheers,
Daniil

Muskan Paliwal July 18, 2023

Hi @Daniil,

Thanks a lot for your response. I have checked it twice and that I am sending each and every value correctly. Would you mind helping me out here via a small meeting?

Would be a huge help, since if the flow doesn't work, we will have to skip using oauth consumers and have to find any other way to deal with authentication in bitbucket.

 

Thanks, 

Muskan

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events