Uploaded image for project: 'Jira Data Center'
  1. Jira Data Center
  2. JRASERVER-76340

Scripts failing intermittently due to permissions denied (401) exception while using PAT

XMLWordPrintable

      Issue Summary

      This is reproducible on the Data Center: Yes

      Steps to Reproduce

      1. Create two Jira users: UserA and UserB and two Projects: ProjectA and ProjectB.
      2. Restrict access to ProjectA for UserA, and ProjectB for UserB
      3. Create one issue each on ProjectA and ProjectB.
      4. Use the below python script to access the Jira issues. 
        import requests
        import threading
        import base64
        
        
        #==============================================================================================================================#
        baseUrl =       "Pass the Jira base URL here"                             # base URL of the instance
        
        userA = {
            "issue":    "Pass the ProjectA issue id here",                                             # issue only User A can access
            "name":     "UserA",                                            # username of User A
            "pat":      "PAT of UserA"      # PAT of User A
        }
        userB = {
            "issue":    "Pass the ProjectB issue id here",                                             # issue only User B can access
            "name":     "userB",                                            # username of User B
            "pat":      "PAT of UserB"      # PAT of User B
        }
        
        usePAT = True                                                       # True = PAT Authentication / False = Basic Authentication
        #==============================================================================================================================#
        
        
        stop = False
        def getIssue(thread, user):
            global stop
            count = 0
            countError = 0
        
            if usePAT:
                headers = {"Authorization": f"Bearer {user['pat']}", "X-Atlassian-Token": "nocheck"}
            else:
                usrPass = base64.b64encode(bytes(f'{user["name"]}:{user["password"]}', 'utf-8')).decode()
                headers = {"Authorization": f"Basic {usrPass}", "X-Atlassian-Token": "nocheck"}
        
            while not stop:
                response = requests.get(f"{baseUrl}/rest/api/latest/issue/{user['issue']}", headers=headers)
                if count % 100 == 0:
                    print(f"[Thread #{thread}] {countError} errors in {count} attempts.\n", end='')
        
                if(response.status_code != 200):
                    countError = countError + 1
                    print(f"[Thread #{thread}] Error on attempt {count}!\n", end='')
        
                count = count+1
        
        # Comment out one of these threads and the errors will stop
        threading.Thread(target=getIssue, args=(1, userA)).start()
        threading.Thread(target=getIssue, args=(2, userB)).start()
        
        input()
        stop = True 
      5. Execute the Python script.

      Expected Results

      The User ID defined in a Python script should not change automatically.

      Actual Results

      The User ID defined in the Python script changed automatically.

      For example:
      As per "AO_81F455_PERSONAL_TOKEN" DB entry, the token id of User JIRAUSER10100 and JIRAUSER10101 are 231996917591 and 165303034442 respectively.

      Following is the log trace that shows the successful authentication of User JIRAUSER10100 using token id 231996917591

      2023-10-05 17:57:46,714+0530 http-nio-42015-exec-25 TRACE anonymous 1077x12278x2 - 0:0:0:0:0:0:0:1 /rest/api/latest/issue/PROJ-1 [c.a.p.web.filter.TokenBasedAuthenticationFilter] Auth SUCCESS for user: [JIRAUSER10100] and tokenId: [231996917591] and expiry:[2024-01-03 17:29:09.506]

      After executing the Python scripts you will notice that the User ID of UserB is being used for accessing the issue using the token ID of UserA on a few attempts. Basically, the UserID is getting updated automatically from UserA (JIRAUSER10100) to UserB (JIRAUSER10101)
      Updated here with the sample log snippet from atlassian-jira.log after enabling the debug package "com.atlassian.pats.web.filter.TokenBasedAuthenticationFilter" to "TRACE".

      2023-10-05 17:57:46,729+0530 http-nio-42015-exec-7 TRACE anonymous 1077x12280x2 - 0:0:0:0:0:0:0:1 /rest/api/latest/issue/ABCD-774 [c.a.p.web.filter.TokenBasedAuthenticationFilter] Auth failure: [Authentication failed for user: 'JIRAUSER10100' and tokenId: '165303034442']
      

      The access log entry will look like this:

      0:0:0:0:0:0:0:1 1071x2618x2 - [05/Oct/2023:17:57:46 +0530] "GET /j82015/rest/api/latest/issue/ABCD-774- HTTP/1.1" 401 136 40 "-" "python-requests/2.27.1" "-"
      

      Workaround

      Add a retry logic in the script to re-initiate the script in case of failures.

              4efd9de64ab4 Mingyi Yang
              e6507c4d83bb Vaisakh S
              Votes:
              16 Vote for this issue
              Watchers:
              34 Start watching this issue

                Created:
                Updated:
                Resolved: