How to authenticate Nodejs connect app for JIRA Cloud?

Hi,

I have been trying to create a JWT token using atlassian-jwt library and pass that as “Authorization” header to make rest api calls in my nodejs app but keep getting error message

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<status>
  <status-code>401</status-code>
  <message>Client must be authenticated to access this resource.</message>
</status>

I am using ClientKey for iss and SharedSecret for secret to create JWT token…Is this correct?
When I install Addon, the response I get back has the following

{
pid: xxxx,
clientkey: xxxxx,
public key: xxxxxxxx,
sharedSecret: xxxxxxxx,
and some other fields
}

Can someone guide me with respect to creating of valid JWT token and making REST API calls from a nodejs app?

Assuming that you are referring to this atlassian-jwt library, can you share the code snippet when you created the token? Also, please share how you called the REST API.

As an aside, I use atlassian-connect-express when working with Node.js - it was fairly straight forward when I used it before. Might be worth checking if it can help you out.

Cheers!

Thanks iragudo
I would like to keep the code simple to begin with…using connect express library means I am adding code which I don’t understand at the moment and half of it I might not need it as well. So I am trying to generate a simple JWT token and trying to update a Jira issue.

Below is the sample code from my small app

  const req = jwt.fromMethodAndUrl('PUT', '/rest/api/3/issue/XX-21?overrideScreenSecurity=true&overrideEditableFlag=true');

    const tokenData = {
        "iss": 'addon-key',
        "iat": now.unix(),                    // The time the token is generated
        "exp": now.add(3, 'minutes').unix(),  // Token expiry time (recommend 3 minutes after issuing)
        "qsh": jwt.createQueryStringHash(req) // [Query String Hash](https://developer.atlassian.com/cloud/jira/platform/understanding-jwt/#a-name-qsh-a-creating-a-query-string-hash)
    };

    const token = jwt.encode(tokenData, secret);
  axios.defaults.headers.common['Authorization'] = `JWT ${token}`;
  let options = {
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: `{
      "fields": {
        "xy-coordinates": {
          "x": "${location.xValue}",
          "y": "${location.yValue}"
        }
      }
    }`
  }

  axios.put('https://sample.atlassian.net/rest/api/3/issue/${key}?overrideScreenSecurity=true&overrideEditableFlag=true', options)
  .then(res => {
    console.log(res)
    res.sendStatus(200)
    res.end()
  })
  .catch(err => console.log(err))

Can you let me know what am I missing in this request as the error message I get back is

<h1>Unauthorized (401)</h1>

Hi,

Where from do you get secret in your code?

It is essential part, if you look at atlassian-connect-express, you may see that secret is obtained upon registering the app in Jira (aka handshake)

Thank you.

Yes, I retrieve it from the Installed callback response when app is registered in JIRA. I save that sharedSecret and use it to generate the token.

@iragudo any help would be appreciated

Hmm… I do not see any glaring issues in the code you’ve placed. To isolate the issue, can you try a REST API that does not have some sort of variable (issue ID) in it? For example, try Get current user REST API.

If that works, it probably means that the JWT generation is correct but there might be some problem when you call jwt.fromMethodAndUrl (maybe the parameters?). If it still does not work, maybe there’s something going on with atlassian-jwt.

I haven’t used the library in a while, I might’ve missed something.