pycontribs / jira

Python Jira library. Development chat available on https://matrix.to/#/#pycontribs:matrix.org
https://jira.readthedocs.io
BSD 2-Clause "Simplified" License
1.94k stars 860 forks source link

Unable to login using `basic_auth` method #1658

Open hialvaro opened 1 year ago

hialvaro commented 1 year ago

Bug summary

When trying to authenticate Jira, I use the following, as the docs indicate:

jira = JIRA(server="https://somecompany.atlassian.net", basic_auth=("user@company.com", jira_api_token))

However, I am getting the following error:

JIRAError: JiraError HTTP 401 url: https://somecompany.atlassian.net/rest/api/2/myself
    text: Client must be authenticated to access this resource.

    response headers = {'Date': 'Wed, 17 May 2023 19:12:08 GMT', 'Content-Type': 'application/json;charset=UTF-8', 'Server': 'AtlassianEdge', 'Timing-Allow-Origin': '*', 'X-Arequestid': 'xxxxx', 'X-Seraph-Loginreason': 'AUTHENTICATED_FAILED', 'Cache-Control': 'no-transform', 'Vary': 'Accept', 'Www-Authenticate': 'OAuth realm="https%3A%2F%2Fsomecompany.atlassian.net"', 'X-Content-Type-Options': 'nosniff', 'X-Xss-Protection': '1; mode=block', 'Atl-Traceid': '9d3333336121598a', 'Report-To': '{"endpoints": [{"url": "https://xxxxopenkxxxs.cloudfront.net"}], "group": "endpoint-1", "include_subdomains": true, "max_age": 600}', 'Nel': '{"failure_fraction": 0.001, "include_subdomains": true, "max_age": 600, "report_to": "endpoint-1"}', 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload', 'Transfer-Encoding': 'chunked'}
    response text = {"message":"Client must be authenticated to access this resource.","status-code":401}

However, if I use it like this:

jira = JIRA(server="https://somecompany.atlassian.net", options={"headers": {"Authorization": f"Basic {jira_api_token}"}})

It works perfectly. Is there some issue with token authentication? Am I missing something?

Is there an existing issue for this?

Jira Instance type

Jira Cloud (Hosted by Atlassian)

Jira instance version

No response

jira-python version

3.5.0

Python Interpreter version

3.9

Which operating systems have you used?

Reproduction steps

1. Use the following, as the docs indicate, to authenticate (with proper variables):

jira = JIRA(server="https://somecompany.atlassian.net", basic_auth=("user@company.com", jira_api_token))

Getting the following error:

JIRAError: JiraError HTTP 401 url: https://somecompany.atlassian.net/rest/api/2/myself
    text: Client must be authenticated to access this resource.

    response headers = {'Date': 'Wed, 17 May 2023 19:12:08 GMT', 'Content-Type': 'application/json;charset=UTF-8', 'Server': 'AtlassianEdge', 'Timing-Allow-Origin': '*', 'X-Arequestid': 'xxxxx', 'X-Seraph-Loginreason': 'AUTHENTICATED_FAILED', 'Cache-Control': 'no-transform', 'Vary': 'Accept', 'Www-Authenticate': 'OAuth realm="https%3A%2F%2Fsomecompany.atlassian.net"', 'X-Content-Type-Options': 'nosniff', 'X-Xss-Protection': '1; mode=block', 'Atl-Traceid': '9d3333336121598a', 'Report-To': '{"endpoints": [{"url": "https://xxxxopenkxxxs.cloudfront.net"}], "group": "endpoint-1", "include_subdomains": true, "max_age": 600}', 'Nel': '{"failure_fraction": 0.001, "include_subdomains": true, "max_age": 600, "report_to": "endpoint-1"}', 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload', 'Transfer-Encoding': 'chunked'}
    response text = {"message":"Client must be authenticated to access this resource.","status-code":401}

### Stack trace

```python
File "/tmp/windmill/dt-worker-2YIZc-MGtr3/01882b20-7646-e743-05c1-7a8801bc4f89/f/DevOps/create_jira_issue.py", line 24, in main
    print(jira.myself())
          ^^^^^^^^^^^^^

  File "/tmp/windmill/cache/pip/jira==3.5.0/jira/client.py", line 3150, in myself
    return self._get_json("myself")
           ^^^^^^^^^^^^^^^^^^^^^^^^

  File "/tmp/windmill/cache/pip/jira==3.5.0/jira/client.py", line 3871, in _get_json
    r = self._session.get(url, params=params)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/tmp/windmill/cache/pip/requests==2.30.0/requests/sessions.py", line 600, in get
    return self.request("GET", url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/tmp/windmill/cache/pip/jira==3.5.0/jira/resilientsession.py", line 241, in request
    elif raise_on_error(response, **processed_kwargs):
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/tmp/windmill/cache/pip/jira==3.5.0/jira/resilientsession.py", line 69, in raise_on_error
    raise JIRAError(

Expected behaviour

Authenticate and proceed to what I need to do.

Additional Context

No response

adehad commented 1 year ago

Could you check if the just released 3.5.1 has any improved behaviour?

mbernier commented 1 year ago

I was only able to get this to work with jira 3.5.1 with the following, only passing one of the auth methods wouldn't work, but when I passed both I was able to access without auth errors.

jira = JIRA(server="https://somecompany.atlassian.net", 
            basic_auth=(jira_email, jira_token),
            options={"headers": {"Authorization": f"Basic {jira_token}"}})
adehad commented 1 year ago

I'll whip up a pull request where we use the HTTPBasicAuth class from requests to see if it helps.

It's quite strange that our Jira Cloud test suite passes. For now that is the only difference that comes to mind

adehad commented 1 year ago

Actually, something just came to mind. Are we using the correct token here? This client is leveraging the requests library that is already base64 encoding the email:token, https://github.com/psf/requests/blob/6e5b15d542a4e85945fd72066bb6cecbc3a82191/requests/auth.py#L62-L64 .

If you are able to pass a raw header of f"Basic {jira_token}" that suggests to me that you are using the incorrect token.

Could you elaborate further on what token you are using and where you are getting it from?

Here are the links to the Atlassian docs that may help: https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/#supply-basic-auth-headers

IOR88 commented 12 months ago

In my case this solved the problem

ACCESS_TOKEN = ""

CLOUD_ID = ""

options = {
    'server': f'https://api.atlassian.com/ex/jira/{CLOUD_ID}'
    # "headers": {
    #     'Authorization': f'Bearer {ACCESS_TOKEN}'
    #            }
           }
j = JIRA(
    options=options, token_auth=ACCESS_TOKEN)
Niyojan commented 5 months ago

For some weird reason, it was not working, was getting the same error as mentioned in the bug summary, but the same code then started working by itself. Not sure why, below is the code for reference

from jira import JIRA

jira_token = 'token'
jira = JIRA(
    server='https://myorg.atlassian.net',
    basic_auth=('my@email.com', jira_token),
)

print(jira.issue('ORG-301').fields.summary)

Same code as in the docs, but still sharing.