0
votes

I'm following the tutorial found here to create a JWT token to access the REST API of JIRA. I do not have any problem accessing endpoints without passing query strings like /rest/api/2/project and /rest/api/2/issue/ISSUE-KEY but I get 401 Unauthorized when trying to pass query strings, say /rest/api/2/user/assignable/search?project=PROJECT-KEY

I'm guessing I'm missing out something, specificially the generation of canonical URL,

Here is the code that generates the get request and JWT token:

@Override
public CloseableHttpResponse get(String url) throws HttpException,
        IOException, NoSuchAlgorithmException, ParseException,
        JOSEException {
    CloseableHttpClient client = HttpClientBuilder.create()
            .setUserAgent("Kevin 6.9").build();
    String token = createToken(url, JIRAClient.Method.GET);
    HttpGet method = new HttpGet(jwt.getBaseUrl() + url);
    method.setHeader("Authorization", "JWT " + token);
    return client.execute(method);
}

/**
 * Create JWT token
 * 
 * @return
 * @throws UnsupportedEncodingException
 * @throws NoSuchAlgorithmException
 */
private String createToken(String apiPath, JIRAClient.Method method)
        throws UnsupportedEncodingException, NoSuchAlgorithmException {
    long issuedAt = System.currentTimeMillis() / 1000L;
    long expiresAt = issuedAt + 1000L;
    String httpMethod = method.toString();
    System.out.println(httpMethod);

    String contextPath = "/jira";

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

    HashMap<String, String[]> parameters = new HashMap<String, String[]>();
    CanonicalHttpUriRequest canonical = new CanonicalHttpUriRequest(
            httpMethod, apiPath, contextPath, parameters);
    System.out.println("Canonical : " + canonical.getRelativePath());
    JwtClaimsBuilder.appendHttpRequestClaims(jwtBuilder, canonical);

    JwtWriterFactory jwtWriterFactory = new NimbusJwtWriterFactory();
    String jwtbuilt = jwtBuilder.build();
    String jwtToken = jwtWriterFactory.macSigningWriter(
            SigningAlgorithm.HS256, jwt.getSharedSecret()).jsonToJwt(
            jwtbuilt);

    return jwtToken;
}

Note that I am passing an empty HashMap<String, String[]> to the CanonicalHttpUriRequest... is this correct?

1

1 Answers

0
votes

Apparently the Map<String, String[]> is required to generate the appropriate canonical URI.

Note that I am passing an empty HashMap<String, String[]> to the CanonicalHttpUriRequest... is this correct?

I modified my method signature so I can pass it as a parameter. Note: createQueryString is a method inside my class that manually creates the query String from the parameter map.

@Override
public CloseableHttpResponse get(String url,
        @SuppressWarnings("rawtypes") Map parameters) throws Exception {
    CloseableHttpClient client = HttpClientBuilder.create()
            .setUserAgent("Kevin 5.0").build();
    String token = createToken(url, JIRAClient.Method.GET, parameters);
    HttpGet method = new HttpGet(jwt.getBaseUrl() + url
            + createQueryString(parameters));
    method.setHeader("Authorization", "JWT " + token);
    return client.execute(method);
}

And it works.

@Test
public void testJQL() throws Exception {
    HashMap param = new HashMap();
    param.put("jql", new String[] {"project=COR"});
    param.put("startAt", new String[] {"0"});
    HttpResponse response = client.get("/rest/api/2/search", param);
    Assert.assertTrue(response.getStatusLine().getStatusCode() == 200);
}