Upload attachment to JIRA Issue via Java servlet using using JWT

387 views
Skip to first unread message

Salvatore Cammarata

unread,
Jul 22, 2014, 5:56:08 AM7/22/14
to atlassian-...@googlegroups.com
Hi,
I am trying to upload an attachment via REST API and JWT authentication but the POST request receive a "401: Unauthorized" response.

The JWT token seems to be created correctly and if I use a basic authentication the attachment is properly created on the issue.

The connect add-on is correctly installed and it is already able to download an attachment from an issue using JWT authentication.

Is there something I am doing wrong?

Following is the code used to create the JWT token (using the jwt-api, jwt-core library):

...

baseUrl
= "http://salvatores-macbook-pro.local:2990/jira"
apiPath
= "/rest/api/latest/issue/10100/attachments"
method
= "POST"

...


static public String createJwt(String key, String sharedSecret, String method, String baseUrl, String contextPath, String apiPath)
       
throws UnsupportedEncodingException, NoSuchAlgorithmException {
   
long issuedAt = System.currentTimeMillis() / 1000L;
   
long expiresAt = issuedAt + 180L;


   
JwtJsonBuilder jwtBuilder = new JsonSmartJwtJsonBuilder()
           
.issuedAt(issuedAt)
           
.expirationTime(expiresAt)
           
.issuer(key);


   
CanonicalHttpUriRequest canonical = new CanonicalHttpUriRequest(method,
            apiPath
, contextPath, new HashMap<String, String[]>());
   
JwtClaimsBuilder.appendHttpRequestClaims(jwtBuilder, canonical);


   
JwtWriterFactory jwtWriterFactory = new NimbusJwtWriterFactory();
   
String jwtBuilt = jwtBuilder.build();
   
String jwtToken = jwtWriterFactory.macSigningWriter(SigningAlgorithm.HS256,
            sharedSecret
).jsonToJwt(jwtBuilt);


   
return jwtToken;
}

Here is the code of the code of the servlet:

private void upload(HttpServletResponse resp, String jwt, String url, String filename) throws IOException
{

    CloseableHttpClient httpclient = HttpClients.createDefault();

    HttpPost httppost = new HttpPost(url);
    httppost.setHeader("X-Atlassian-Token", "nocheck");

// Basic authorization works!
//        String jira_attachment_authentication = new String(org.apache.commons.codec.binary.Base64.encodeBase64(("admin:admin").getBytes()));
//        httppost.setHeader("Authorization", "Basic " + jira_attachment_authentication);
    httppost.setHeader("Authorization", "JWT "+ jwt);

    InputStream is = getServletContext().getResourceAsStream("/" + filename);
    ByteArrayBody fileBody = new ByteArrayBody(IOUtils.toByteArray(is), filename);

    HttpEntity entity = MultipartEntityBuilder.create()
            .addPart("file", fileBody)
            .build();

    httppost.setEntity(entity);
    String mess = "Executing request " + httppost.getRequestLine();
    log.info(mess);

    CloseableHttpResponse response;

    try {
        response = httpclient.execute(httppost);
    } finally {
        httpclient.close();
    }

    resp.setContentType("application/json");
    resp.getWriter().print("{ response: " + response.getStatusLine().getStatusCode() + ", reason: " + response.getStatusLine().getReasonPhrase() + "}");
}




Yves Berquin

unread,
Jul 22, 2014, 6:03:18 AM7/22/14
to atlassian-...@googlegroups.com
Hello Salvatore,

Have you tried providing the jwt as a query parameter like this:
    HttpPost httppost = new HttpPost(url + "?jwt=" + jwt);
(at the proper place in your code of course).
I've always used that method and it seems to work fine for me.

Yves
Message has been deleted

Salvatore Cammarata

unread,
Jul 22, 2014, 7:04:37 AM7/22/14
to atlassian-...@googlegroups.com
Yves,
Thanks for the suggestion.
I am not sure why, but now, luckily, the same code is working. Anyway, at least let's hope that the code posted will be useful as a reference for somebody with the same needs :)

PS Putting the JWT in the header works too!

Yves Berquin

unread,
Jul 22, 2014, 7:08:23 AM7/22/14
to atlassian-...@googlegroups.com
Good to know you're unlocked.
And I will definitely use this trick of putting the JWT in the header. It's a lot cleaner than adding as a parameter in my opinion.
Besides that, it's funny to see that your code is using exactly the same libraries and all as ours :)

Yves


--
You received this message because you are subscribed to the Google Groups "Atlassian Connect Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to atlassian-connec...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Peter Brownlow

unread,
Jul 22, 2014, 8:41:28 PM7/22/14
to atlassian-...@googlegroups.com
Hmm... so the code posted above was not working and then, without modification, it started working?

For the sake of thoroughly making sure that we don't have a bug, if it happens again can you post the relevant logs from the host product? You should see at least one log line relating to the 401 response, possibly multiple log lines.
To unsubscribe from this group and stop receiving emails from it, send an email to atlassian-connect-dev+unsub...@googlegroups.com.

David Benson

unread,
Dec 11, 2015, 3:39:15 PM12/11/15
to Atlassian Connect Dev
Salvatore, have you ever tried a unicode filename in your example? I'm getting failure (i.e. "????????" filenames) on both UTF-8 and non UTF-8 default charset systems.
Reply all
Reply to author
Forward
0 new messages