Two-legged OAuth between PHP and JIRA

If you want to use the JIRA REST API without storing plain-text passwords in your application, you need to use OAuth. If you want the application to directly talk to JIRA without binding it to a JIRA user account, you need to use 2-legged OAuth. JIRA requires RSA keys for 2-legged OAuth. Zend_OAuth supports RSA-signed requests, but this is somewhat undocumented. Also, the Java OAuth library used by JIRA appears to have a bug that requires the field oauth_token in the Authorization header to be present but blank for 2-legged authentication (if it’s not present, it raises uncaught exceptions…). Lastly, you have to use the exact server name that JIRA thinks it has. Finding out all this took me quite a while, so here is the full code:

PHP Code

require_once 'Zend/Oauth.php';
require_once 'Zend/Oauth/Consumer.php';
require_once 'Zend/Crypt/Rsa/Key/Private.php';
require_once 'Zend/Crypt/Rsa/Key/Public.php';
$jql = 'project = KB';
$max = 50;
$server = 'https://www.example.com/jira/'; // this must not be http://localhost:8080. It must match the proxyName, proxyPort and Context configured in ./conf/server.xml in JIRA. Otherwise you get signature_invalid exceptions
$query = array('jql' => $jql, 'startAt' => '0', 'maxResults' => $max, 'fields' => 'summary,assignee,duedate,priority')
$privkey = new Zend_Crypt_Rsa_Key_Private('jira.pem');
$pubkey = new Zend_Crypt_Rsa_Key_Public('jira.pub');
$consumer = 'samplescript';
$query['oauth_token'] = ''; // otherwise you get uncaught net.oauth.OAuthProblemException: signature_invalid exceptions
$oauth_config = array(
 'consumerKey' => $consumer,
 'rsaPrivateKey' => $privkey,
 'rsaPublicKey' => $pubkey,
 'signatureMethod' => 'RSA-SHA1',
 'siteUrl' => $server . '/plugins/servlet/oauth',
 'requestScheme' => Zend_Oauth::REQUEST_SCHEME_QUERYSTRING,
 );
$oauth = new Zend_Oauth_Consumer($oauth_config);
$oauth->setSignatureMethod('RSA-SHA1');
$oauth->setRsaPrivateKey($privkey);
$oauth->setRsaPublicKey($pubkey);
$token = new Zend_Oauth_Token_Access(); // 2-legged authentication doesn't use tokens, but this is the only way to get a HTTP Client that sets the proper Authorization headers
$oauth->setToken($token);
$client = $token->getHttpClient($oauth_config, $url);
$client->setUri(sprintf('%s/search', $url));
$client->setMethod(Zend_Http_Client::GET);
$client->setParameterGet($query);
$json = json_decode($client->request()->getBody());
print_r($json);

Generating the keys

openssl genrsa -out jira.pem 1024
openssl rsa -in jira.pem -pubout -out jira.pub

Registering them with JIRA

Go to the JIRA Administration, click Plugins, then Application Links.

Click Add Application Link, enter your server URL, enter the name of your application and select Generic Application.

Now configure it: got to Incoming Authentication, set a Consumer Key (I used samplescript above), set a name and paste the contents of jira.pub into the box. Now check 

JIRA OAuth configuration

7 thoughts on “Two-legged OAuth between PHP and JIRA

  1. motions

    I tried to use your code but i always get 500 error, any idea of this, i installed latest zend framework but still no success under logs i see PHP Fatal error: Class ‘OAuthConsumer’ not found in

  2. vafirmrak

    Hello, Michael! I can’t find where defined $url in your article.

  3. Pingback: Migrating JIRA to osTicket | Michael Kuron's Blog

  4. Faye

    JIRA 7.2, and I don’t understand why I don’t see the “Allow 2 legged OAuth option”.
    Any ideas as to why?

Leave a Reply

Your email address will not be published. Required fields are marked *