Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Jira Platform Oauth 2(3LO): Unable to get auth code

Hello, I am tasked to write an integration to pull data from Jira cloud. The cloud has oauth 2 auth with the app and such already set up. I am following this documentation here (https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/#frequently-asked-questions).

The constraint is that this is integration is a script running from a node server which will not be able to open a web page to authorize and get that code from the URL in step one.

Is there anyway around this such as different api call?

 

Also, I tried to manually inputting the generated auth code into the script for the POST call in step 2 but it still doesn't like it. 

 

 

1 answer

1 accepted

1 vote
Answer accepted
Dario B Atlassian Team Jul 02, 2021

Hello @John Huynh ,

From your explanation:

this is integration is a script running from a node server which will not be able to open a web page

 

Therefore, as written in the Jira Cloud platform Developer - Security Overview page, Oauth2 is not the right way to go. You should use Basic authentication with an Atlassian account email address and API token instead:

[...]

Security is implemented differently, depending on what you are building:

  • Forge apps
  • Connect apps
  • OAuth 2.0 (3LO) apps
  • Scripts or other REST API clients

[...]

Scripts and other REST API clients

Scripts and other REST API clients use basic authentication. Basic authentication uses an API token to authenticate the client. The token is generated from a user's Atlassian Account, encoded, then added to the header for requests to the API.

Authorization for basic authentication is based on the permissions of the user you used to generate the API token. For example, if you're using basic authentication, your user must have the Administer projects permission for a project to call PUT /rest/api/3/project/{projectIdOrKey} (Update project).

We recommend that you only use basic authentication if you have other security measures in place.

To learn more, read Basic auth for REST APIs.

 

I hope this helps.

 

Finally, for the future, please notice that this is not the best place to get help on development  related questions. The right resources are listed in https://developer.atlassian.com/resources. 

Specifically:

 

Cheers,
Dario

Hi Dario,

 

Thanks for the reply. Just a follow up question, would oauth1 method be the same as it requires a verification code from the callback url?

 

Best,

John

Dario B Atlassian Team Jul 09, 2021

@John Huynh ,

Oauth1 could actually work in your case, I didn't mention it since it is deprecated and I am not sure if it will be removed in the near future.

That's because, even if you need to authenticate request token once in order to get the access token, this will then last 5 years as mentioned in the documentation:

An access code is all that is needed to make an authenticated request to the Jira REST API. Requests are made as the user who authorized the initial request token. The access token will persist for 5 years, unless it is revoked.

 

For more details please see:

 

Cheers,
Dario

Like John Huynh likes this

@Dario B 

 

Good to know! For my specific case, what is the recommended best practice? 

 

Also if I go down the Oauth1 path, what would these two properties be in translated to in the request headers as?

Screen Shot 2021-07-09 at 2.33.36 AM.png

 

Thanks,

John

Dario B Atlassian Team Jul 09, 2021

@John Huynh ,

I am not 100% sure since this is not something I usually do and since this is actually not the best place to get support on development questions.

However, looking at the Oauth1 RFC (authorization header section), I believe they should be oauth_token and oauth_consumer_key:

3.5.1.  Authorization Header

   Protocol parameters can be transmitted using the HTTP "Authorization"
   header field as defined by [RFC2617] with the auth-scheme name set to
   "OAuth" (case insensitive).

   For example:

     Authorization: OAuth realm="Example",
        oauth_consumer_key="0685bd9184jfhq22",
        oauth_token="ad180jjd733klru7",
        oauth_signature_method="HMAC-SHA1",
        oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
        oauth_timestamp="137131200",
        oauth_nonce="4572616e48616d6d65724c61686176",
        oauth_version="1.0"

   Protocol parameters SHALL be included in the "Authorization" header
   field as follows: ......
.....
..

 

 

However, as mentioned in the Tips section of the OAuth 1.0a for REST APIs (Legacy) page, it is advised to use Oauth libraries already available, rather than implement everything yourself:

  • Use OAuth libraries: Rather than implement everything yourself, there are several OAuth libraries that you can use at Code at OAuth.net. The example OAuth client uses the Google OAuth Client Library for Java.
  • Requests for tokens must be made using HTTP POST.
  • Set the callback to oob (out of band) when creating the request token if you want to show the token secret to the user: See getAndAuthorizeTemporaryToken in JiraOAuthClient.java in the example OAuth client for an example of this. You can then set the callback to another URL after the user authorizes the token, so that Jira sends the token and secret to that URL.
  • Pass the OAuth access token in the request header, not request body, when making requests: Passing the OAuth data in the request body returns a 400 Bad Request error for most methods. Pass the data in the header instead.
  • When making requests for a temporary token, append the query string to the path: Don't send consumer_key or other parameters using the authorization header.

 

I hope this helps.

Like John Huynh likes this

Hi Dario,

 

So we decided to take it the basic authentication route with API token, I follow what was described in the documentation below and added it as Authorization value in the headers.

https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/

 

But then, I got this error from Jira api:

[2021-07-27T21:03:14.752Z] [ERROR] -             {
              "response": {
                "body": "Basic authentication with passwords is deprecated.  For more information, see: https://confluence.atlassian.com/cloud/deprecation-of-basic-authentication-with-passwords-for-jira-and-confluence-apis-972355348.html\n",
                "statusCode": 401,
                "headers": {
                  "server": "AtlassianProxy/1.19.3.1",
                  "content-type": "text/plain",
                  "strict-transport-security": "max-age=315360000; includeSubDomains; preload",
                  "date": "Tue, 27 Jul 2021 21:03:14 GMT",
                  "atl-traceid": "17a172271f4f1f83",
                  "x-xss-protection": "1; mode=block",
                  "transfer-encoding": "chunked",
                  "x-content-type-options": "nosniff",
                  "connection": "close",
                  "expect-ct": "report-uri=\"https://web-security-reports.services.atlassian.com/expect-ct-report/global-proxy\", enforce, max-age=86400"
                }
              },

 

The directed url leads to a blog post with little information.

https://confluence.atlassian.com/cloud/deprecation-of-basic-authentication-with-passwords-for-jira-and-confluence-apis-972355348.html

 

Can you please advise?

Dario B Atlassian Team Jul 28, 2021

Hi @John Huynh ,

It looks like either the email address or the API token are not recognized and therefore the error message returned is saying that you cannot use basic authentication with password anymore.

Can you kindly try to send a REST API call using the same email address with Curl in order to double check whether the issue is with the provided credentials or with the Java code that is building the authorization header.

Something like below example:

curl -u <EMAIL-ADDRESS>:<API-TOKEN> -D- -X GET "https://XXXXXXXXX.atlassian.net/rest/api/3/issue/TSP-26"

HTTP/2 200
server: AtlassianProxy/1.19.3.1
vary: Accept-Encoding
cache-control: no-cache, no-store, no-transform
content-type: application/json;charset=UTF-8
strict-transport-security: max-age=315360000; includeSubDomains; preload
date: Wed, 28 Jul 2021 16:53:37 GMT
atl-traceid: d51b5c13a3ada827
x-arequestid: 814403e3-93c2-44b8-b1a7-14143aec6e4a
x-aaccountid: XXXXXXXXXXXXXXXXXXXXXX
x-xss-protection: 1; mode=block
timing-allow-origin: *
x-envoy-upstream-service-time: 366
x-content-type-options: nosniff
set-cookie: atlassian.xsrf.token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_lin; Path=/; Secure
expect-ct: report-uri="https://web-security-reports.services.atlassian.com/expect-ct-report/global-proxy", enforce, max-age=86400

{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations,customfield_10105.requestTypePractice","id":"10554","self":"https://XXXXXXXXXX.atlassian.net/rest/api/3/issue/10554","key":"TSP-26"

 

Please replace the issue key with one that exist in your Jira site and hide the sensitive data like in above example before pasting the result in your reply.

Like John Huynh likes this

@Dario B 

Here is the results from the curl command:

curl -u <email>:<api_token> -D- -X GET "https://<jira-url>.atlassian.net/rest/api/3/issue/OPE-278"

HTTP/2 200 

server: AtlassianProxy/1.19.3.1

vary: Accept-Encoding

cache-control: no-cache, no-store, no-transform

content-type: application/json;charset=UTF-8

strict-transport-security: max-age=315360000; includeSubDomains; preload

date: Wed, 28 Jul 2021 21:26:07 GMT

atl-traceid: c11e27b5517d65cc

x-arequestid: 5708f179-75fb-46f8-bc89-c9aca428cd41

x-aaccountid: 602eb7212a42cc0069937e4e

x-xss-protection: 1; mode=block

timing-allow-origin: *

x-envoy-upstream-service-time: 314

x-content-type-options: nosniff

set-cookie: atlassian.xsrf.token=BVI9-VGJB-U0KA-B2OU_3fbd8a66862b39598def56cc7fc111f5381e6e76_lin; Path=/; Secure

expect-ct: report-uri="https://web-security-reports.services.atlassian.com/expect-ct-report/global-proxy", enforce, max-age=86400




{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations,customfield_19110.requestTypePractice","id":"10132","self":"https://<jira-url>.atlassian.net/rest/api/3/issue/10132","key":"OPE-278","fields": .... }}

 

Curl seems to work and returning data, but unfortunately the script I am working on is NodeJs so I am not sure what are the nuances there. 

 

I noticed that the curl call uses api version 3 and what I am using is api version 2, so I tried switching in my code with no luck.

 

{
              "response": {
                "body": "Basic authentication with passwords is deprecated.  For more information, see: https://confluence.atlassian.com/cloud/deprecation-of-basic-authentication-with-passwords-for-jira-and-confluence-apis-972355348.html\n",
                "statusCode": 401,
                "headers": {
                  "server": "AtlassianProxy/1.19.3.1",
                  "content-type": "text/plain",
                  "strict-transport-security": "max-age=315360000; includeSubDomains; preload",
                  "date": "Wed, 28 Jul 2021 18:09:16 GMT",
                  "atl-traceid": "e53dec55e394e8c0",
                  "x-xss-protection": "1; mode=block",
                  "transfer-encoding": "chunked",
                  "x-content-type-options": "nosniff",
                  "connection": "close",
                  "expect-ct": "report-uri=\"https://web-security-reports.services.atlassian.com/expect-ct-report/global-proxy\", enforce, max-age=86400"
                }
              },
              "request": {
                "method": "POST",
                "host": "<jira-url>.atlassian.net",
                "port": 443,
                "path": "/rest/api/3/search",
                "headers": {
                  "Content-Type": "application/json",
                  "Accept": "application/json",
.....
.

 

 

Hi @John Huynh ,

Based on the results of your test, there seems to be an issue on how the authentication header is built in the nodeJS app.

Would it be possible to copy-paste the related lines of code in here?

Also, another way to troubleshoot this would be the following:

  1. Create a mock endpoint using https://beeceptor.com/ (or requestbin or any other similar tool) like for example: something.free.beeceptor.com
  2. Send an authenticated request to the endpoint created in previous step using Curl
  3. Send the same request to the same endpoint using your NodeJS code
  4. Access the beeceptor console (for the example url it would be beeceptor.com/console/something), expand the headers for both requests and look for differences.

 

You can check below screenshots for more details:

beeceptor-1.jpg    header-beeceptor.jpg

 

 

For more details on how the authorization header should be built please refer to the Supply basic auth headers section of the Basic auth for REST APIs documentation page.

 

 

Cheers,
Dario

Like John Huynh likes this

Ah, I have found what was wrong with it with your suggestion!

It was a bad encoding with my node script. Thanks for the all the help!

Like Dario B likes this
Dario B Atlassian Team Jul 30, 2021

I am happy to know this helped @John Huynh :) 

Please do not hesitate to get in touch with us in the future in case of any other issue or concern and enjoy your weekend!

Dario

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
STANDARD
TAGS
Community showcase
Published in Bamboo

Bamboo Data Center Apps Program coming soon

G’day Bamboo customers, As we approach GA for Bamboo Data Center , we would like to inform you that the Data Center Apps Program for Bamboo starts this quarter. How long does it take? We are g...

69 views 0 6
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you