Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Trying to use Scribe library for 2 legged Oauth in JIRA

Jason Plumhoff
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.
November 10, 2014

I've been trying to use the Scribe Java library to allow my application to authenticate with JIRA and create issues in it. Unfortunately, I seem to have hit a wall. No matter what I do, my test script (see below) fails saying I'm not authenticated. I'm confused by this, and can't figure out where I'm going off the rails.  I've spent 3 solid days on this and have run out of things to try.  If you can help, please see the info below.  Any help would be deeply appreciated!

Thanks, Jason

 

Here's how I got where I am now:

1) Successfully created a public/private key pair using:

 

openssl genrsa -out mykey.pem 1024
openssl rsa -in mykey.pem -pubout > mykey.pub

 

 

2) Created a "generic application" link in JIRA.  The parameters are:

 

Application Name: "AP2J"
Application Type: Generic Application
Application/Display URL: "http://www.google.com" <-- just a placeholder
Outgoing Authentication: Disabled
Incoming Authentication: Oauth/Configured
     Consumer Key: AP2J
     Consumer Name: AP2J
     Description: None
     Public Key: <Public key extracted in step 1> 
     Consumer Callback URL: None
     Allow 2-Legged Oauth: True
     Execute as: <A particular user with verified access to issue TOOL-1>
     Allow impersonation?: False

 

3) Created a Groovy script to test the connection:

package com.plasmatherm.jira.oauthtest

import org.scribe.builder.ServiceBuilder
import org.scribe.model.OAuthRequest
import org.scribe.model.Response
import org.scribe.model.SignatureType
import org.scribe.model.Token
import org.scribe.model.Verb
import org.scribe.oauth.OAuthService

OAuthService service = new ServiceBuilder()
        .provider(JiraAPI.class)
        .apiKey("AP2J")
        .apiSecret("AP2J") // Is this my problem?  Where do I get the API Secret?
        .signatureType(SignatureType.QueryString)
        .debug()
        .build()

OAuthRequest request = new OAuthRequest(Verb.GET, "http://&lt;our.test.Jira.instance&gt;/rest/api/latest/issue/TOOL-1") 
//Note: TOOL-1 issue not visible to unauthenticated users

service.signRequest(Token.empty(), request)
Response response = request.send()
System.out.println(request.completeUrl.toString())
System.out.println(response.getBody())

I took the JiraAPI class from http://stackoverflow.com/questions/14127418/scribe-and-atlassian-rest.  Maybe the problem is in here, because the question had no solution (well, it had a response where somebody said it was impossible - but their reasoning was incorrect).  On the other hand, since I'm using 2 legged oauth, the only part of this class that gets called is the getPrivateKey method, and I know that is working...:

package com.plasmatherm.jira.oauthtest

import net.oauth.signature.Base64
import org.scribe.builder.api.DefaultApi10a
import org.scribe.model.Token
import org.scribe.services.RSASha1SignatureService
import org.scribe.services.SignatureService
import java.security.KeyFactory
import java.security.PrivateKey
import java.security.spec.PKCS8EncodedKeySpec

public class JiraAPI extends DefaultApi10a {
    static final String BASE = "http://vm-jira:8080/plugins/servlet";
    @Override
    public String getAccessTokenEndpoint()
    {
        return BASE + "/oauth/access-token";
    }
    @Override
    public String getAuthorizationUrl(Token requestToken)
    {
        return BASE + "/oauth/authorize?oauth_token="+requestToken.getToken();
    }
    @Override
    public String getRequestTokenEndpoint()
    {
        return BASE + "/oauth/request-token";
    }
    @Override
    public SignatureService getSignatureService() {
        return new RSASha1SignatureService(getPrivateKey());
    }
    private static PrivateKey getPrivateKey()
    {
        String str = "&lt;My private key in PKCS8 format&gt;";
        try
        {
            KeyFactory fac = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(str.getBytes()));
            return fac.generatePrivate(privKeySpec);
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }
}

 

4) Ran the Groovy script.  It fails with the response:

{"errorMessages":["You are not authenticated. Authentication required to perform this operation."],"errors":{}}

 

 

 

 

1 answer

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

0 votes
Answer accepted
Jason Plumhoff
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 5, 2014

Finally got it to work (sort of). I added an appender I found in a JIRA ticket to my log4j.properties so I could watch JIRA handle OAuth requests:

#####################################################
# OAUTH-309: This appender adds additional logging for OAUTH
#####################################################
log4j.appender.applinksConfigAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.applinksConfigAppender.datePattern='-'dd'.log'
log4j.appender.applinksConfigAppender.File=applinks.log
log4j.appender.applinksConfigAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.applinksConfigAppender.layout.ConversionPattern=%d %t %p [%c{4}] %m%n

... and then in JIRA -> System -> Logging and Profiling I set the com.atlassian.oauth logging level to DEBUG. I could now see oauth requests being made on the system from our Confluence instance and from dashboard gadgets, but my program still wasn't generating any log entries.

Even though I wasn't planning on using impersonation (in the incoming authentication section of my application link, I had JIRA set to execute the 2-legged request using a specific user), I put in the 'user_id' parameter and set it equal to a user I knew had access to the issue I was testing against. This still didn't work.

I finally got JIRA to tell me what was wrong when I included the 'oauth_token' parameter in my request and set it equal to an empty string. From all my reading, I shouldn't have had to do that, but oh well. Once I did that, the oauth request started showing up in the log. But it was giving an error:

2-Legged-OAuth with Impersonation request has been attempted but 2-Legged-OAuth with Impersonation is not enabled for consumer:'someconsumer'. Cannot access resource as user 'someuser'

So then I realized that I needed to set "Allow user impersonation through 2-Legged OAuth" to true. Once I did this (AND included the user_id parameter), everything worked.

I still don't know why any of this was necessary. And I would like it to work without impersonation - but I'll settle for this right now.

TAGS
AUG Leaders

Atlassian Community Events