Connecting OAuth2.0 authentication to confluence API with Python

Lauren Watters September 2, 2021

I want to connect the confluence API using python code to extract data and information for my company's platform. 

I have an admin account and I have used a URL to request a connection to the account:

# Connecting to the confluence API
response = requests.post("https://admin.atlassian.com/s/3264ff5d-6218-4e57-a69a-894f103a800b/content",
json = {
"APIKey": ""

}
)

This code when ran gives the status code of 403 Forbidden. I am sure that the URL I am using is correct and the API key also. However, I am unsure as to why I cannot grant access to the system and it is forbidden.

Is there a way to authenticate the requests to the URL to ensure that it runs and I get back a 200 status code?

I have looked at the OAuth2.0 Authentication on the confluence documentation page, however, it is difficult to understand as the code is not in python and it is hard to put into context of how it would be used in a situation like this.

If anyone is able to help, or explain how I would authenticate the requests using my admin account in python that would be great.

2 answers

1 accepted

1 vote
Answer accepted
Jacob Brunson
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
September 2, 2021

Hi @Lauren Watters

My name is Jacob, and I'm a Confluence Cloud developer. My expertise isn't in OAuth, but I can try to help.

First I would like to recommend: do not share your API key with anybody; treat it like a password. If the API key you posted above is real, you should immediately go to the following URL and revoke the token: https://id.atlassian.com/manage-profile/security/api-tokens


OAuth is quite complicated. If what you're trying to accomplish is more like a data-collection script and not necessarily an application intended to be used by others, I would suggest using "Basic auth" if possible. If you do need OAuth, I would suggest taking advantage of an OAuth library for Python, such as OAuth lib.


If you can use Basic auth, great! It's much more straightforward and it's easy to use with the Python `requests` library which I see you're using.

First, you need to take your API token, and concatenate it with your email address, separated by a colon, for example: "jacob@example.com:abc123xyz"

Next, you need to base64 encode that string. There's a variety of ways to do it, but with Python it would be:

import base64
# The string we're encoding should be "<your-email>:<your token>"
auth_key = base64.b64encode("jacob@example.com:abc123xyz")

Finally, you need to add an Authorization header to your request. Assuming you use the `auth_key` variable from the code above it would look something like:

# Using the base64 encoded auth_key string from above
# The "Basic " (including space) is important
headers
= { "Authorization": "Basic " + auth_key }

# Fire your request, attaching the authorization header
response = requests.post("https://admin.atlassian.com/s/3264ff5d-6218-4e57-a69a-894f103a800b/content", headers=headers)

You can find some official documentation for what I just described here: https://developer.atlassian.com/cloud/confluence/basic-auth-for-rest-apis/

I hope this helps! If not, don't hesitate to reach out.

Best,

Jacob

Lauren Watters September 3, 2021

Hi Jacob, @Jacob Brunson 

Thank you for taking the time to look at the problem and give some helpful feedback. I have removed the API key. I'm still new to this so wasn't aware of how protected they should be.

I'm unsure as to what sort of authentication I should use for what data I need to capture. My requirements are to capture the following from the Confluence API:

  1. Current Project Status by client
  2. Current project status by Innovation
  3. Risks on current projects
  4. Folder of current Videos for both client & innovation projects

The code you showed above for basic auth is explained very well and makes a lot of sense when converted into python as the code on the documentation webpage is not in python and hence hard to convert for a newbie like me.

 

I tried the code you showed exactly and checked it a few times, however I was granted with an error message which I will show below and im not sure why. If you have time to review the code and see where I may have gone wrong that would be great. (I didnt include the API key this time as I have learnt from your previous message):

import base64
import requests

# The string we're encoding should be "<your-email>:<your token>"
auth_key = base64.b64encode("lauren.watters@therobotexchange.com:api-key")
print(auth_key)
# Using the base64 encoded auth_key string from above
# The "Basic " (including space) is important
headers = { "Authorization": "Basic " + auth_key}

# Fire your request, attaching the authorization heade
response = requests.post("https://admin.atlassian.com/s/3264ff5d-6218-4e57-a69a-894f103a800b/content", headers=headers)

print(response.status_code)
if response:
print('Request is successful.')
else:
print('Request returned an error.')

This left me with the following error:

image.png

I thought of a way round this by using an online encoder for the email:api-key, and used the following code below. But this then returned the 403 forbidden status code once again. Im really not sure as to why I cant seem to grant access to the confluence account to be able to pull the required data from this. 

import base64
import requests

# The string we're encoding should be "<your-email>:<your token>"
# I have edited the auth key by removing parts, left it in to show as an example
auth_key1 = "bGF1cmVuLndhdHRlcnNAdGhlcm9ib3Rl-----------api-key----------Z6a0tBTDlPOEs2ak9EQUQ0"

# Using the base64 encoded auth_key string from above
# The "Basic " (including space) is important
headers = { "Authorization": "Basic " + auth_key1}

# Fire your request, attaching the authorization header
response = requests.post("https://admin.atlassian.com/s/3264ff5d-6218-4e57-a69a-894f103a800b/content", headers=headers)
print(response.status_code)
if response:
print('Request is successful.')
else:
print('Request returned an error.')

Capture.PNG

If you have any ideas as to why this still isnt giving me access that would be great. Im really unsure as to where to go from this.

Once again, I really appreciate all the time taken to think of a solution and reply to me.

 

Thanks,

Lauren

Jacob Brunson
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
September 3, 2021

Hi Lauren!

I apologize for the bad b64encode instructions. I was testing using the outdated Python 2, while you're using the modern Python 3. The code I should've posted is:

auth_key = base64.b64encode(b"jacob@example.com:abc123cyz").decode("ascii")

Regardless, your use of an online encoder should work just as well!


I should've noticed this earlier, but I think the problem you may be facing now is that the admin.atlassian.com URL you're requesting is not a valid part of the API. I just tried a similar URL myself and got the same 403 result. You would need to use one of the functions described in the Confluence Cloud REST API documentation. Each function will have 3 important parts: the URL, the "method" (in your case it will usually be "GET"), and the parameters.

For example, to get a list of content from therobotexchange Confluence, you would use GET /wiki/rest/api/content:

response = requests.get("https://therobotexchange.atlassian.net/wiki/rest/api/content", headers=headers)

(Assuming your Confluence site can be found at https://therobotexchange.atlassian.net/wiki)

If the request is successful, it will return a JSON string. You can convert this into a Python object by using the `json` function:

data = response.json()

Thanks for sharing your requirements. It's difficult for me to give specific directions for which API functions to use because I'm not sure how your data is organized in Confluence. Are you using Confluence Spaces and Pages to manage this data? Maybe using labels? Depending on how your data is structured, you should be able to find an appropriate API function in the API documentation linked above. All of the different functions are listed in the left sidebar.

Hope this gets you started! 

Best,
Jacob

Lauren Watters September 7, 2021

Hi @Jacob Brunson

 

Sorry for the late reply. I have tried this new solution you suggested and it works great! Finally get the status code 200 returned and I am now able to extract the data by using the confluence rest API documentation. 

 

Thanks for all the advice and help, I appreciate it!

 

Have a good week :) 

Like Jacob Brunson likes this
0 votes
Faisal Ladak October 21, 2021

Hi @Jacob Brunson

I am a newbie with Python and APIs. I have confluence on the server and I created the API token using this link https://id.atlassian.com/manage-profile/security/api-tokens. I tried following this thread and have the following code generating 401 status. Will you please see if there are any obvious mistakes? I have changed the ID and token before publishing here.

 

import base64
import requests

auth_key = base64.b64encode(b"abc@def.com:ShJoVuXcVWOp66NIxWXk275CXX").decode("ascii")
print(auth_key)
headers = { "Authorization": "Basic " + auth_key}

response = requests.post("https://confluence.mycompany.io", headers=headers)

print(response.status_code) ## yields 401

Jacob Brunson
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
October 22, 2021

Hi @Faisal Ladak 

If you're using Confluence Server, then the authentication will work a bit differently than it does on Confluence Cloud.

For basic auth, instead of using an API token you should be able to use your password.

For example, 

import base64
import requests

auth_key = base64.b64encode(b"abc@def.com:yourpasswordhere123").decode("ascii")
print(auth_key)
headers = { "Authorization": "Basic " + auth_key}

response = requests.post("https://confluence.mycompany.io", headers=headers)

Hope this helps. Happy coding!

Faisal Ladak October 25, 2021

@Jacob Brunson Thank you for your response. I tried the code provided by you and still, it comes back with 401. My code is as follows:

import base64
import requests

auth_key = base64.b64encode(b"abc@def.com:pwpwpwp").decode("ascii")
print(auth_key)
headers = { "Authorization": "Basic " + auth_key}

response = requests.post("https://confluence.def.io", headers=headers)
print(response.status_code)

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
STANDARD
TAGS
AUG Leaders

Atlassian Community Events