I am trying to create an application for Jira Service Desk, however, I keep getting stuck at the following point:
After successfully generating a valid JWT, I try to access the rest URL via cURL, but I keep getting 401, unauthorized.
This is the function where I call the JWT-creature function:
public function generateJWT() {
$j = new JWTModel();
$o = new ObjectModel();
$r = new RestModel();
$object = $o->getClientByUrl('https://<my-instance-for-demo>.atlassian.net');
$jwt = $j->generate(10000, $object->key, $object->clientKey, $object->sharedSecret);
print_r($r->issueData($jwt, 10000));
}
This is the function that creates the JWT:
public function generate($issue, $key, $clientKey, $sharedSecret) {
$token = [
"iss" => $key,
"iat" => time(),
"exp" => time() * 3600,
"sub" => $clientKey,
"qsh" => hash('sha256', "GET&/rest/api/latest/issue/" . $issue)
];
$jwt = JWT::encode($token, $sharedSecret);
return $jwt;
}
And eventually the cURL-function:
public function issueData($jwt, $issue) {
try {
$curl = new Curl();
$curl->setOpt(CURLOPT_SSL_VERIFYPEER, false);
$curl->setOpt(CURLOPT_POST, false);
$curl->setOpt(CURLOPT_HTTPHEADER, ['Authorization: JWT ' . $jwt, 'Content-type: application/json']);
$curl->post("https://<my-instance-for-demo>.atlassian.net/rest/api/latest/issue/" . $issue);
return $curl->response;
} catch (\ErrorException $e) {
return $e->getMessage();
}
}
This is my connect:
{
"name": "XXXX XXX",
"description": "XXX makes your life easier",
"key": "xxxx-app",
"baseUrl": "https://xxx.xxxx.nl",
"vendor": {
"name": "xxxx",
"url": "http://xxx.nl"
},
"links": {
"self": "https://xxx.xxx.nl/atlassian-connect.json",
"homepage": "https://xxx.nl/"
},
"authentication": {
"type": "jwt"
},
"lifecycle": {
"installed": "/installed",
"uninstalled": "/unstalled"
},
"scopes": [
"READ"
],
"apiVersion": 1,
"modules": {
"webPanels": [{
"conditions": [{
"condition": "user_is_logged_in"
}],
"key": "xxx-xxx-insert",
"name": {
"value": "xxx"
},
"url": "/canned?project={servicedesk.serviceDeskId}&issueId={issue.id}&issueKey={issue.key}",
"location": "atl.jira.view.issue.left.context",
"layout": {
"width": "100%",
"height": "100px"
},
"weight": 999
}]
}
}
Does anyone sees the point where I made a mistake?
Hi Willem-Jelle,
For your cURL-function, please use $curl->get() instead of $curl->post();
Oh and a side note, @Willem-Jelle der Nederlanden ... I noticed in your original code, the expiry time is time() * 3600 - should that not be time() + 3600? :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi thereI am trying something similar ... Also my first time working on Connect Apps. Here is a sample code I am using. I am running this locally and on my Test server ... and both returns a 401.
```<?php
require_once('vendor/autoload.php');
use \Firebase\JWT\JWT;
$key = 'test-key-used-in-app-desc';$iat = (int) time();$exp = $iat + 3600;$sec = 'URiDszs6dEQZeTrBRc5H1FwIbdoVnvYmVlgsSIAqduji5NUndVFwvtin0XawuJWa6wLcOoBbUvbinkJCqMTChe';$method = 'GET';$baseUrl = 'https://xxx.atlassian.net';$path = '/rest/api/3/search';$qs = str_replace('?', '&', '?maxResults=100');$qshStr = $method.'&'.$path.'&'.substr($qs, 1);$qsh = hash('sha256', $qshStr);$claims = array( "iss" => $key, "exp" => $exp, "iat" => $iat, "qsh" => $qsh);
$jwtToken = JWT::encode($claims, $sec);$apiUrl = $baseUrl.$path.'?jwt='.$jwtToken;$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $apiUrl);curl_setopt($ch, CURLOPT_HTTPGET, true);curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Accept: application/json'));curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$curl_response = curl_exec($ch);echo '<pre>';print_r(json_decode($curl_response, true));echo'</pre>';curl_close($ch);```
Please advise where I am going wrong?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Yatish Madhav Hi, it looks like your QSH value is incorrect. It is required to put the path in the QSH. Let me know if that solves the problem!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks @Willem-Jelle der Nederlanden - I have resolved this an hour or two after I posted it ... So yes, I did include the path ($qshStr = $method.'&'.$path.'&'.substr($qs, 1);)
So this was the issue. The QSH was correct ... but when I was making the call, I did not include the "maxResults=100" query string. And that caused the match between the 2 to fail - hence not authorizing myself. :)
Thanks for the quick reply too ...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.