...
JSON Web Tokens consist of three parts separated by dots (.
), which are:
Header
Payload
SignatureeSignature
Therefore, a iHub JWT looks like the following.
...
Code Block |
---|
{
"iss": "client_id_from_atlassian",
"sub": "flow_id",
"aud": "https://ihubprod.rixter.net/prod/incoming/token",
"iat": "currentTimeSeconds",
"exp": "plus currentTimeSeconds 1200",
"flow": "flow_id"
} |
Output from the signed will be xxxxx.yyyyy.zzzzz
...
To exchange the JWT to a short lived bearer token, do a
POST to https://ihubprod.rixter.net/token and if incoming/token
Body:
Code Block |
---|
{
"grant_type":"urn:ihub:jwt:bearer",
"assertion":"{{JWT}}"
} |
Replace the {{JWT}} with the signed token from above step.
This URN structure indicates:
urn: Namespace denoting a Uniform Resource Name
ihub: Identifies the IHub system
jwt: Specifies a JSON Web Token (JWT)
bearer: Indicates the token type is bearer
Response
If valid it will return a body like below
Code Block |
---|
{
" access_token": "0AY_VpZg4WI2L0VYjXAc9ccwpNwj2TYbAJ-p_o2pCHHXWGK1N_ADhZ93y0e2REPitoJkbWs-VsEby0pTQXj1tP-5Wh8RTgbqKY343JvMhU_5EKf1vwXA8jUXeANWte-om4yGBIxbI7CUodb1hOfRuIw23RdSHHvvUWsKraffuJ0xpOr5sLTzc3NAdsak4Xjc8IjujDMoHDoEqECzL12CCCrVnkiDuGPN4TNnLbBPnqM91L-6a5WlC-bD3EetEmW7lS3R0GK7HLexgMiAwhKc9EXIaV3v_nwJZp2STQZcxc8Q4YcqCtKgOsSfrPb87MQ3z2FE2sBOmhIziLBS5WifWvYaBhWcyvxifWxj5aw7Ad0GvKRQzsbdP2GwGN385D42jpSupk9oxui84wuq6wr9bRsWagYwQjto-x2y7gZwyrMVyQpBOy_3QhhIY32Xw6vJoOj-2ypRWaIXnhzUyfJkfJv5j_4a8F_grpI9wigVS1X5cdkIBiis-ZuvYvkx8fIJ0nn59bFsomi1qvJ9pMyWByVZ4w2yeyuso7-Q2qRX0jrWbRrOsOMsl5xQoOZYZRm-bFz66ynd-3q50qjcr2QtdQy_ZXcQSZ1bkQjwio7x0jz_Yptn9Bfl2geOeioze__d-_9xd1ZZMwixbYvWuxklh8hvakVyIkc9ZfBMo5dMen6l89Wy0tsq5-65zvB8SZyfk-qikWic_ouVo26kJ1Xe-ni36dxxzoxM-Vu4Wuq3kJ58QhVcUhj9m6zzk866trqqJnx28cBJQ9ofhf8BjcOilO-bt8dJV-ZrRS2-vyFZq9_1d9tvMZe6WJ1JoVbQx7tne_7S8y3Jn2n3Frc18loQ9__Ye_5ic04ed367srWvi-1ojYbOM79hy5mnu2VMU6isFz_hUVqqj5Z-xXZIsQ02vW0g_uIltq85waObt8wYziv4lZU--UUZ1h72McynvY81gqQlB4uVIb6Sp_XprXYtgIOsIYkuQsp7so9ls4Rl7l52Zdkd1W29IF2w",
"token_type": "Bearer",
"expires_in": 3599'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI0ZjAxOWQ0My00OTAwLTNhOTgtYWEwNi00NjE0M2Y0MGMwNjEiLCJzdWIiOiIzNGNkMzNlNC1iNmFhLTQ4MzctODc1Yi03ZWQ4MWFhMzk2ZDYiLCJleHAiOjE3MTkzMTk0MDMsImlhdCI6MTcxOTMxOTA4MX0.jljJZJMcYD4PapgraNXoZZWUYOR3mPcTgpd_CUeeqCU',
token_type: 'Bearer',
expires_in: 1719319403
} |
Use the Bearer token
To trigger the flow send the request to https://ihubprod.rixter.net/incoming/webhook/jwt with the http header Authorization: Bearer {{access_token}}
In this call you will include any data that the integration will process.
Example code for trigging flow
Python
Code Block |
---|
pip install PyJWT requests cryptography |
The private key is stored in a file called privateKey.txt in this example
Expand |
---|
|
Code Block |
---|
import jwt
import requests
import time
import os
from pathlib import Path
import unittest
class TestIncomingJWTIntegration(unittest.TestCase):
def setUp(self):
self.timeout = 10 # seconds
self.maxDiff = None
def test_should_return_a_valid_bearer(self):
headers = {
"alg": "RS256",
"typ": "JWT"
}
current_time = int(time.time())
payload = {
'iss': 'copy from trigger page',
'sub': 'copy from trigger page',
'aud': 'https://ihubprod.rixter.net/prod/incoming/token',
'iat': current_time,
'exp': current_time + 1200
}
private_key_path = Path(__file__).parent / 'privateKey.txt'
with open(private_key_path, 'r') as file:
private_key = file.read()
token = jwt.encode(payload, private_key, algorithm='RS256', headers=headers)
# print('Generated JWT:', token)
data = {
"grant_type": "urn:ihub:jwt:bearer",
"assertion": token
}
access_token = None
# test generate jwt
try:
response = requests.post(payload['aud'], json=data, headers={'Content-Type': 'application/json'})
response.raise_for_status()
access_token = response.json().get('access_token')
except requests.exceptions.RequestException as error:
print('Error:', error.response.json() if error.response else str(error))
self.assertIsNotNone(access_token)
# test trigger flow
incoming_data = {
"issueKey": "SERVICENOW-1",
"description": "HEJ",
"summary": "Ticket from test case"
}
try:
response = requests.post(
"https://ihubprod.rixter.net/prod/incoming/webhook/jwt",
json=incoming_data,
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {access_token}'
}
)
response.raise_for_status()
print(response.json())
except requests.exceptions.RequestException as error:
print('Error:', error.response.json() if error.response else str(error))
if __name__ == '__main__':
unittest.main()
|
|
Javascript
The private key is stored in a file called privateKey.txt in this example
Expand |
---|
title | Javascript example code |
---|
|
Code Block |
---|
var jwt = require('jsonwebtoken');
const axios = require('axios');
import { expect } from "chai";
const fs = require('fs');
const path = require('path');
describe('Incoming JWT integration test', function() { // Use function() to access this.timeout
this.timeout(10000); // Increase timeout to 10 seconds
it('should return a valid bearer', async () => {
const headers = {
"alg": "RS256",
"typ": "JWT"
};
const currentTime = Math.floor(Date.now() / 1000);
const payload = {
iss: 'copy from trigger page',
sub: 'copy from trigger page',
aud: 'https://ihubprod.rixter.net/prod/incoming/token',
iat: currentTime,
exp: (currentTime + 1200)
};
const privateKeyPath = path.join(__dirname, 'privateKey.txt');
const privateKey = fs.readFileSync(privateKeyPath, 'utf8');
const token = jwt.sign(payload, privateKey, { algorithm: 'RS256', header: headers });
//console.log('Generated JWT:', token);
const data = {
"grant_type": "urn:ihub:jwt:bearer",
"assertion": token
};
let access_token;
//test generate jwt
try {
const response = await axios.post(payload.aud, data, {
headers: {
'Content-Type': 'application/json'
}
});
access_token = response.data.access_token;
} catch (error) {
console.error('Error:', error.response ? error.response.data : error.message);
}
expect(access_token).not.to.be.equal(undefined);
//test trigger flow
const incomingData = {
"issueKey": "SERVICENOW-1",
"description": "HEJ",
"summary":"Ticket from test case"
};
try {
const response = await axios.post("https://ihubprod.rixter.net/prod/incoming/webhook/jwt", incomingData, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+access_token
}
});
console.log(response.data)
} catch (error) {
console.error('Error:', error.response ? error.response.data : error.message);
}
});
});
|
|