Jira Service Desk problem: custom JWT verification for external API calls in atlassian-jwt plugin 3.

Aidin Mahmoodi _ServiceRocket_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
September 22, 2019

I am posting this here since we didn't get an answer on the dev community, thought here I might get more visibility and hopefully an answer.

TL;DR how to make this work? There are no actual examples anywhere on how to use this SPI, and this is a blocker for a number of our customers.

We recently have a problem with our app. When a customer installs Jira Service Desk, our external API calls are not properly authorized, which results in a 401. After a bit of investigation, the cause of it seems to be the Atlassian JWT plugin (which is installed along with JSD). Long story short, the JWT token our calls use to have an issuer and shared secret unrecognized by the plugin, which causes them to be rejected.

I have spent a considerable amount of time trying to solve it, let me describe what I tried so far.

According to https://bitbucket.org/atlassian/atlassian-jwt/src/master/ 1, the newest version (3.1.0) of the JWT plugin allows you to register your own claim verifiers along with your issuer and shared secret, through the newest SPI. I made sure 3.1.0 is installed by my plugin (the last JSD uses 3.0.0 by default, where the SPI would not be available yet). That went without problems

Next, I implemented a simplified Jwt Issuer registry and Jwt Issuer Claim Verifier registry classes, so that Jira could pick up the right data for my plugin. Similarly, I implemented an example Claim verifier builder, which would be returned by my registry. (the code is in Scala)

@ExportAsService({
Array(classOf[JwtIssuerRegistry])
})
@Component
@Named("pluginJwtIssuerRegistry")
class PluginJwtIssuerRegistry extends JwtIssuerRegistry {
case class PluginJwtIssuer(name: String, sharedSecret: String) extends JwtIssuer {
override def getName: String = name

override def getSharedSecret: String = sharedSecret
}

override def getIssuer(issuer: String): JwtIssuer = PluginJwtIssuer(issuer, "sharedSecretPlaceholder")
}

@ExportAsService({
Array(classOf[JwtIssuerClaimVerifiersRegistry])
})
@Component
@Named("pluginJwtIssuerClaimVerifiersRegistry")
class PluginJwtIssuerClaimVerifiersRegistry extends JwtIssuerClaimVerifiersRegistry {
override def getClaimVerifiersBuilder(issuer: String): JwtClaimVerifiersBuilder =
new ServerCustomJwtClaimVerifierBuilder(false)
}

class ServerCustomJwtClaimVerifierBuilder(verifyHash: Boolean) extends JwtClaimVerifiersBuilder {
override def build(request: CanonicalHttpRequest): util.Map[String, _ <: JwtClaimVerifier] =
ClaimVerifiers.NO_REQUIRED_CLAIMS
}

In order to ensure those classes are visible to the JWT plugin, I added the following configuration in the section of the AMPS in my plugin pom.xml:

<Export-Package>
com.servicerocket.jira.salesforce.rest.auth.jwt,
com.atlassian.jwt
</Export-Package>

 The registries definitely do show up in the OSGI view of the UPM in jira

422a04300d99188148f57531767e28713b186ff2.png

This seems to be exactly in sync with the atlassian-spring-scanner-maven-test-service-exporting-plugin example provided in the atlassian spring scanner ( https://bitbucket.org/atlassian/atlassian-spring-scanner/src/master/ )

However, none of it seems to be picked up by the JWT plugin. When I connect my debugger to the com.atlassian.jwt.internal.PluginJwtRegistry.java class, the only Issuer registries visible to the tracker seem to be coming from Applinks and JSD; no sign of the services I exported.

Since the stack for our app is Scala, I was a bit worried about the compatibility of the Java annotations. And so, I also tried declaring the beans explicitly in the plugin-context.xml in META-INF:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:atlassian-scanner="http://www.atlassian.com/schema/atlassian-scanner"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://www.atlassian.com/schema/atlassian-scanner
http://www.atlassian.com/schema/atlassian-scanner/atlassian-scanner.xsd"
default-autowire="autodetect">
<atlassian-scanner:scan-indexes/>
<beans:bean id="pluginJwtIssuerClaimVerifiersRegistry"
class="com.servicerocket.jira.salesforce.rest.auth.jwt.PluginJwtIssuerClaimVerifiersRegistry"/>
<osgi:service id="pluginJwtIssuerClaimVerifiersRegistry_osgiService" ref="pluginJwtIssuerClaimVerifiersRegistry"
interface="com.atlassian.jwt.JwtIssuerClaimVerifiersRegistry"/>
<beans:bean id="pluginJwtIssuerRegistry"
class="com.servicerocket.jira.salesforce.rest.auth.jwt.PluginJwtIssuerRegistry"/>
<osgi:service id="pluginJwtIssuerRegistry_osgiService" ref="pluginJwtIssuerRegistry"
interface="com.atlassian.jwt.JwtIssuerRegistry"/>
</beans>

That didn’t achieve anything, either. The registry beans declared this way show up in the OSGI UPM view just the same, and they’re also not picked up by the Atlassian JWT plugin.

I'll appreciate any kinda help.

 

 

0 answers

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events