How to test the Jira Incoming Link OAuth 2.0 API
Platform notice: Server and Data Center only. This article only applies to Atlassian products on the Server and Data Center platforms.
Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Summary
The Jira OAuth 2.0 provider API describes an overview explaining how OAuth2.0 works. To complement the explanation you may want to test this feature.
Warning
Please be aware of the Jira URLs, code, client id, client secret, token, and all other variables are from an internal system used as a sample and will change regarding each system. These will be different once you do it in your own Jira instance.
Environment
- 8.22.x (the feature only available in 8.22 release)
- 9.x
- 10.x
Diagnosis
It is not clear how to test the Jira OAuth2.0 as a provider and you want to implement this solution to integrate Jira with external applications.
Solution
In a nutshell please follow the below steps:
Pre-reqs:
- Jira must run on SSL please see Running Jira applications over SSL or HTTPS.
- An application link must be created to the external application as described in Configure an incoming link.
In JIRA UI go to Jira Administration (cog icon) > Applications > Application links
- Create an incoming application link to the External application
- Give a name
- Add a redirect URL
- Choose the permission you want to grant to the application
The example has all the steps made in one internal system with the below data:
- client_id=38843a89f2b02a471000bc022e4b9de8
- client_secret=f2a497f753230b7f6eb01a0ac2e8f64e71f6900ee9976354c4f0b97d01829f92
- redirect_uri=https://localhost:8091/jira
- Jira base URL = https://localhost:8091/jira
- scope=SYSTEM_ADMIN (if you are selecting permission to System Admin, see scopes)
https://localhost:8091/jira is just an example of the Jira Base URL. Please update the URL to the same URL that you configure in your Jira instance.
Using a BROWSER e.g.: Chrome or Firefox
To allow the application
Paste the Jira URL to the browser with the developer tools opened in the network tab:
https://localhost:8091/jira/plugins/servlet/oauth2/consent?client_id=38843a89f2b02a471000bc022e4b9de8&redirect_uri=https://localhost:8091/jira&response_type=code&scope=SYSTEM_ADMIN
- In the developer tools search for the code parameter just after the redirect URI like https://localhost:8091/jira/?code=807570329fd5dad86c254decf7e9d1f3
With the code you can use Postman to make a call to get the token for that you need to POST for example to:
https://localhost:8091/jira/rest/oauth2/latest/token?client_id=38843a89f2b02a471000bc022e4b9de8&client_secret=f2a497f753230b7f6eb01a0ac2e8f64e71f6900ee9976354c4f0b97d01829f92&code=807570329fd5dad86c254decf7e9d1f3&grant_type=authorization_code&redirect_uri=https://localhost:8091/jira
Make sure to add the header "Content-Type: application/x-www-form-urlencoded" to this request.
It will give a response like this:{ "scope": "SYSTEM_ADMIN", "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6Ijk5YjljMmFjZGJmOGFjNjhkMzUzNmQwZjczYzI4ODVjIn0.4VhsFjveavHf_YfCUOQQ1XpXtLVjK-Lam_M-7ldg5DE", "token_type": "bearer", "expires_in": 3600, "refresh_token": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjBlNzlhYjg4MjVkNjFhN2UxNWFjMjdiNmU4NTE2MjM0In0.sQ33w3GCaW6t8xd6f0uFFSnSGlWtnkyCYMHxsKRBuro" }
Use the access_token to call an issue in Jira for example using cURL:
curl -k --header "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpZCI6Ijk5YjljMmFjZGJmOGFjNjhkMzUzNmQwZjczYzI4ODVjIn0.4VhsFjveavHf_YfCUOQQ1XpXtLVjK-Lam_M-7ldg5DE" "https://localhost:8091/jira/rest/api/latest/issue/SRM-25"
It will give you the information from the issue like:
{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations","id":"12742","self":"https://localhost:8091/jira/rest/api/latest/issue/12742","key":"SRM-25","fields":{"issuetype":{"self":"https://localhost:8091/jira/rest/api/2/issuetype/10001","id":"10001","description":"Created by Jira Software - do not edit or delete. Issue type for a user story.","iconUrl":"https://localhost:8091/jira/images/icons/issuetypes/story.svg","name":"Story","subtask":false},"timespent":null,"project":{"self":"https://localhost:8091/jira/rest/api/2/project/10401","id":"10401","key":"SRM","name":"SRM","projectTypeKey":"software","avatarUrls":{"48x48":"https://localhost:8091/jira/secure/projectavatar?avatarId=10324","24x24":"https://localhost:8091/jira/secure/projectavatar?size=small&avatarId=10324","16x16":"https://localhost:8091/jira/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"https://localhost:8091/jira/secure/projectavatar?size=medium&avatarId=10324"}},"fixVersions":[{"self":"https://localhost:8091/jira/rest/api/2/version/10101","id":"10101","name":"Version 1.0","archived":false,"released":true,"releaseDate":"2022-10-04"}],"customfield_10110":5.0,"customfield_10111":null,"aggregatetimespent":null,"resolution":null,"customfield_10700":null,"customfield_10107":"SRM-24","customfield_10108":["com.atlassian.greenhopper.service.sprint.Sprint@3979acde[id=3,rapidViewId=7,state=ACTIVE,name=Sample Sprint 2,startDate=2022-10-05T01:04:37.443+02:00,endDate=2022-10-19T01:24:37.443+02:00,completeDate=<null>,activatedDate=2022-10-05T01:04:37.443+02:00,sequence=3,goal=<null>,autoStartStop=false,synced=false]"],"customfield_10109":"0|i0018s:","resolutiondate":null,"workratio":-1,"lastViewed":"2022-10-17T19:20:55.708+0200","watches":{"self":"https://localhost:8091/jira/rest/api/2/issue/SRM-25/watchers","watchCount":2,"isWatching":true},"created":"2022-10-12T10:17:29.000+0200","customfield_10220":null,"priority":{"self":"https://localhost:8091/jira/rest/api/2/priority/4","iconUrl":"https://localhost:8091/jira/images/icons/priorities/low.svg","name":"Low","id":"4"},"customfield_10100":null,"customfield_10221":null,"customfield_10101":null,"customfield_10222":null,"customfield_10102":null,"customfield_10223":null,"customfield_10300":null,"labels":[],"customfield_10103":null,"customfield_10214":null,"customfield_10215":null,"customfield_10216":null,"customfield_10217":null,"customfield_10218":null,"timeestimate":null,"aggregatetimeoriginalestimate":null,"versions":[],"customfield_10219":null,"issuelinks":[],"assignee":null,"updated":"2022-10-12T10:19:43.000+0200","status":{"self":"https://localhost:8091/jira/rest/api/2/status/10000","description":"","iconUrl":"https://localhost:8091/jira/","name":"To Do","id":"10000","statusCategory":{"self":"https://localhost:8091/jira/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"default","name":"To Do"}},"components":[],"timeoriginalestimate":null,"description":"test of issues in epic","customfield_10210":null,"customfield_10211":null,"customfield_10212":null,"timetracking":{},"archiveddate":null,"customfield_10213":null,"customfield_10600":null,"customfield_10800":null,"attachment":[],"customfield_10207":[{"self":"https://localhost:8091/jira/rest/api/2/user?username=fayres","name":"fayres","key":"JIRAUSER10000","emailAddress":"fayres@atlassian.com","avatarUrls":{"48x48":"https://localhost:8091/jira/secure/useravatar?avatarId=10334","24x24":"https://localhost:8091/jira/secure/useravatar?size=small&avatarId=10334","16x16":"https://localhost:8091/jira/secure/useravatar?size=xsmall&avatarId=10334","32x32":"https://localhost:8091/jira/secure/useravatar?size=medium&avatarId=10334"},"displayName":"Franklin Sanford Ayres","active":true,"timeZone":"Europe/Amsterdam"}],"customfield_10801":null,"aggregatetimeestimate":null,"customfield_10208":null,"customfield_10802":null,"customfield_10209":null,"customfield_10803":null,"customfield_10804":null,"customfield_10805":null,"customfield_10806":null,"customfield_10807":null,"summary":"test1","creator":{"self":"https://localhost:8091/jira/rest/api/2/user?username=fayres","name":"fayres","key":"JIRAUSER10000","emailAddress":"fayres@atlassian.com","avatarUrls":{"48x48":"https://localhost:8091/jira/secure/useravatar?avatarId=10334","24x24":"https://localhost:8091/jira/secure/useravatar?size=small&avatarId=10334","16x16":"https://localhost:8091/jira/secure/useravatar?size=xsmall&avatarId=10334","32x32":"https://localhost:8091/jira/secure/useravatar?size=medium&avatarId=10334"},"displayName":"Franklin Sanford Ayres","active":true,"timeZone":"Europe/Amsterdam"},"subtasks":[],"reporter":{"self":"https://localhost:8091/jira/rest/api/2/user?username=fayres","name":"fayres","key":"JIRAUSER10000","emailAddress":"fayres@atlassian.com","avatarUrls":{"48x48":"https://localhost:8091/jira/secure/useravatar?avatarId=10334","24x24":"https://localhost:8091/jira/secure/useravatar?size=small&avatarId=10334","16x16":"https://localhost:8091/jira/secure/useravatar?size=xsmall&avatarId=10334","32x32":"https://localhost:8091/jira/secure/useravatar?size=medium&avatarId=10334"},"displayName":"Franklin Sanford Ayres","active":true,"timeZone":"Europe/Amsterdam"},"customfield_10000":"{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@69d1a9e6[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@1ba4e34e[overall=PullRequestOverallBean{stateCount=0, state='OPEN', details=PullRequestOverallDetails{openCount=0, mergedCount=0, declinedCount=0}},byInstanceType={}], build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@7939f10f[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@45bbd3f5[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=<null>,lastUpdatedTimestamp=<null>],byInstanceType={}], review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@37c49dd4[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@352bd3d1[stateCount=0,state=<null>,dueDate=<null>,overDue=false,count=0,lastUpdated=<null>,lastUpdatedTimestamp=<null>],byInstanceType={}], deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@32cfdf2[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@1893a219[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=<null>,lastUpdatedTimestamp=<null>],byInstanceType={}], repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@baaa6e2[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@60f4591d[count=0,lastUpdated=<null>,lastUpdatedTimestamp=<null>],byInstanceType={}], branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@453fb9c[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@1d51265[count=0,lastUpdated=<null>,lastUpdatedTimestamp=<null>],byInstanceType={}]},errors=[],configErrors=[]], devSummaryJson={\"cachedValue\":{\"errors\":[],\"configErrors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":\"OPEN\",\"details\":{\"openCount\":0,\"mergedCount\":0,\"declinedCount\":0,\"total\":0},\"open\":true},\"byInstanceType\":{}},\"build\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"failedBuildCount\":0,\"successfulBuildCount\":0,\"unknownBuildCount\":0},\"byInstanceType\":{}},\"review\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":null,\"dueDate\":null,\"overDue\":false,\"completed\":false},\"byInstanceType\":{}},\"deployment-environment\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"topEnvironments\":[],\"showProjects\":false,\"successfulCount\":0},\"byInstanceType\":{}},\"repository\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}},\"branch\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}}}},\"isStale\":false}}","aggregateprogress":{"progress":0,"total":0},"environment":null,"duedate":null,"progress":{"progress":0,"total":0},"comment":{"comments":[{"self":"https://localhost:8091/jira/rest/api/2/issue/12742/comment/11944","id":"11944","author":{"self":"https://localhost:8091/jira/rest/api/2/user?username=agent1","name":"agent1","key":"JIRAUSER10302","emailAddress":"ffayres@gmail.com","avatarUrls":{"48x48":"https://localhost:8091/jira/secure/useravatar?avatarId=10342","24x24":"https://localhost:8091/jira/secure/useravatar?size=small&avatarId=10342","16x16":"https://localhost:8091/jira/secure/useravatar?size=xsmall&avatarId=10342","32x32":"https://localhost:8091/jira/secure/useravatar?size=medium&avatarId=10342"},"displayName":"FraLais Ayres","active":true,"timeZone":"Europe/Amsterdam"},"body":"“This is a comment.\"","updateAuthor":{"self":"https://localhost:8091/jira/rest/api/2/user?username=agent1","name":"agent1","key":"JIRAUSER10302","emailAddress":"ffayres@gmail.com","avatarUrls":{"48x48":"https://localhost:8091/jira/secure/useravatar?avatarId=10342","24x24":"https://localhost:8091/jira/secure/useravatar?size=small&avatarId=10342","16x16":"https://localhost:8091/jira/secure/useravatar?size=xsmall&avatarId=10342","32x32":"https://localhost:8091/jira/secure/useravatar?size=medium&avatarId=10342"},"displayName":"FraLais Ayres","active":true,"timeZone":"Europe/Amsterdam"},"created":"2022-10-12T10:17:30.000+0200","updated":"2022-10-12T10:17:30.000+0200"},{"self":"https://localhost:8091/jira/rest/api/2/issue/12742/comment/11945","id":"11945","author":{"self":"https://localhost:8091/jira/rest/api/2/user?username=fayres","name":"fayres","key":"JIRAUSER10000","emailAddress":"fayres@atlassian.com","avatarUrls":{"48x48":"https://localhost:8091/jira/secure/useravatar?avatarId=10334","24x24":"https://localhost:8091/jira/secure/useravatar?size=small&avatarId=10334","16x16":"https://localhost:8091/jira/secure/useravatar?size=xsmall&avatarId=10334","32x32":"https://localhost:8091/jira/secure/useravatar?size=medium&avatarId=10334"},"displayName":"Franklin Sanford Ayres","active":true,"timeZone":"Europe/Amsterdam"},"body":"issue is being looked at","updateAuthor":{"self":"https://localhost:8091/jira/rest/api/2/user?username=fayres","name":"fayres","key":"JIRAUSER10000","emailAddress":"fayres@atlassian.com","avatarUrls":{"48x48":"https://localhost:8091/jira/secure/useravatar?avatarId=10334","24x24":"https://localhost:8091/jira/secure/useravatar?size=small&avatarId=10334","16x16":"https://localhost:8091/jira/secure/useravatar?size=xsmall&avatarId=10334","32x32":"https://localhost:8091/jira/secure/useravatar?size=medium&avatarId=10334"},"displayName":"Franklin Sanford Ayres","active":true,"timeZone":"Europe/Amsterdam"},"created":"2022-10-12T10:17:31.000+0200","updated":"2022-10-12T10:17:31.000+0200"}],"maxResults":2,"total":2,"startAt":0},"votes":{"self":"https://localhost:8091/jira/rest/api/2/issue/SRM-25/votes","votes":0,"hasVoted":false},"worklog":{"startAt":0,"maxResults":20,"total":0,"worklogs":[]},"archivedby":null}}
- After the token expires, you'd need to make a POST using the refresh_token from before, to get a new token:
https://localhost:8091/jira/rest/oauth2/latest/token?client_id=38843a89f2b02a471000bc022e4b9de8&client_secret=f2a497f753230b7f6eb01a0ac2e8f64e71f6900ee9976354c4f0b97d01829f92&refresh_token=eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjBlNzlhYjg4MjVkNjFhN2UxNWFjMjdiNmU4NTE2MjM0In0.sQ33w3GCaW6t8xd6f0uFFSnSGlWtnkyCYMHxsKRBuro&grant_type=refresh_token&redirect_uri=https://localhost:8091/jira
Make sure to add the header "Content-Type: application/x-www-form-urlencoded" to this request.
Known issues
If you are getting the following error message when using Postman, please change the Authorization type from inherit auth from parent to basic auth and run to generate the access token again. Then, change it back to inherit auth from parent again. This issue happened when Postman does not inherit the auth data correctly:
<title> Unauthorized (401) </title>
If you are getting the following error message when using Postman, please ensure you have the "Content-Type: application/x-www-form-urlencoded" added under Headers tab:
{ "error": "invalid_request", "error_description": "The required parameter 'grant_type' is missing" }
- To customize the OAuth 2.0 behavior, add to setenv.sh the properties from OAuth 2.0 provider system properties.