Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Help Needed with Atlassian Connect App JWT Authentication – 401 Unauthorized Error

Eldar Muzaffarov
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
December 5, 2024

Hi everyone,

I’m currently developing an Atlassian Connect app that needs to authenticate requests to the Jira Cloud REST API using a JWT token. However, I keep getting a 401 Unauthorized error when making requests from my server-side code.

What I’m Trying to Do: I have a Node.js/TypeScript setup where:

  • I store the clientKey, sharedSecret, and baseUrl after installing the Connect app.
  • I generate a JWT token for each request using the atlassian-jwt library, including the qsh claim.
  • I make a GET request to Jira’s /issue/CL-988 endpoint as a test.

Code snippet: 


atlassian-connect.json:

{
"name": "MyCompany Bot",
"description": "MyCompany Bot for Atlassian.",
"key": "com.MyCompany.bot",
"apiVersion": 1,
"baseUrl": "https://{AYN_IP}.ngrok-free.app/atlassian",
"vendor": {
"name": "MyCompany, Inc.",
"url": "https://example.com"
},
"authentication": {
"type": "jwt"
},
"lifecycle": {
"installed": "https://{AYN_IP}.ngrok-free.app/atlassian/installed"
},
"scopes": [
"READ",
"WRITE",
"DELETE",
"PROJECT_ADMIN",
"ADMIN",
"ACT_AS_USER"
],
"modules": {},
"icon": {
"url": "https://{AYN_IP}.ngrok-free.app/atlassian/image.png"
}
}

 

atlassian.service.ts:

import {AtlassianCLientV2} from "./atlassian.client"
public async
getIssueV2(): Promise<any> {
return (await AtlassianClientV2()).get("/rest/api/2/issue/CL-988")
.then(res => res.data)
.catch(e => {
throw new Error(JSON.stringify(e.response.data))
})
}

atlassian.client.ts

import axios, {AxiosInstance, AxiosResponse} from "axios";
import cache from "../utils/cache";
import * as jwt from 'atlassian-jwt';
import moment from 'moment';
import {SymmetricAlgorithm} from "atlassian-jwt/dist/lib/jwt";

 
export async function AtlassianClientV2(): Promise<AxiosInstance> {
const installedData: ConnectHook = await cache.cache("tokens:atlassian:connect:data") as unknown as ConnectHook;

async function createJwtToken(method: string, resource: string): Promise<string> {
console.log(resource)
const token = jwt.encodeSymmetric(
{
iss: installedData.clientKey,
iat: moment().utc().unix(),
exp: moment().utc().add(3, 'minutes').unix(),
qsh: jwt.createQueryStringHash(
jwt.fromMethodAndUrl(method, resource)
)
},
installedData.sharedSecret,
SymmetricAlgorithm.HS256
);
console.log(jwt.decodeSymmetric(token, installedData.sharedSecret, SymmetricAlgorithm.HS256))
return token;
}

const instance: AxiosInstance = axios.create({
baseURL: installedData.baseUrl,
});

instance.interceptors.request.use(async (config) => {
config.headers.Authorization = "JWT " + await createJwtToken(
config.method.toUpperCase(),
config.url
);
config.headers.Accept = 'application/json';
config.headers["Content-Type"] = 'application/json';
return config;
});
console.log(instance.defaults.headers)
return instance;
}



What I’ve Checked So Far:

  • Verified that installedData.clientKey and installedData.sharedSecret are correct.
  • Confirmed that baseUrl is correct, pointing to the Jira Cloud instance (e.g., https://mycompany.atlassian.net).
  • Ensured that the qsh is calculated using only the relative path (e.g., /rest/api/2/issue/CL-988) instead of the full URL.
  • Decoded the JWT on jwt.io to verify claims look correct (iss, iat, exp, qsh).
  • Confirmed that my server’s time is accurate.

Despite these checks, I still receive a 401 Unauthorized response. I would greatly appreciate any guidance on what I might be missing. Are there any additional claims required, or is there a known issue with certain endpoints or HTTP methods? If you need more details, please let me know. Thanks in advance for your help!

 

 

1 answer

Suggest an answer

Log in or Sign up to answer
0 votes
vikram
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 6, 2024

Hi @Eldar Muzaffarov 

Welcome to Atlassian Community. 

Check that end point CL-988 is exist.

try to hard code the API TOKEN (as you are getting authorization error) in your server script and try. 

also try to replace other values with hard code values and test. 

or

If you can post more log files that will help to check further. 

Vikram P

DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
STANDARD
PERMISSIONS LEVEL
Product Admin
TAGS
AUG Leaders

Atlassian Community Events