I develop a connect plugin with Spring-Boot and my plugin has a configuration page with a form. On submit of this form my backend is called, but logs the above error.
Since the atlassian-connect-spring-boot documentation states:
atlassian-connect-spring-boot-starter provides the following features:
...
- Authentication of requests from iframe content back to the add-on
I’d expect that the whole JWT handling is done by the framework.
Did I miss to configure something? My iframe includes the all.js script:
<script src="https://kuespert-dev.atlassian.net/atlassian-connect/all-debug.js" type="text/javascript" data-options="sizeToParent:true;"></script>
and the atlassian-connect.json contains the following authentication entry:
"authentication": {
"type": "jwt"
},
I’m using a standard form and included a hidden parameter ‘jwt’
<form method="POST" id="configuration-form" class="aui">
...
<input type="hidden" name="jwt" value="${atlassianConnectToken}">
...
</form>
How can I get this form to work?
I’m using atlassian-connect-spring-boot version 1.3.5.
Thanks,
Matthias
Thanks for raising this question here, @matthias1 . I don’t immediately see what the problem would be, since the self-authentication tokens don’t even include the query-string hash claim.
Could you provide some logs from your application?
Or would you be able to provide a minimal controller + template to reproduce the issue?
Hi,
thanks for looking into it. The relevant portion of the log (after pressing save) is:
018-01-31 11:13:50.842 DEBUG 50711 --- [nio-3000-exec-5] c.a.c.s.i.a.jwt.JwtAuthenticationFilter : Retrieved JWT from request
2018-01-31 11:13:50.843 DEBUG 50711 --- [nio-3000-exec-5] c.a.c.s.i.a.j.JwtAuthenticationProvider : Parsed JWT: JWTClaimsSet [iss=f8ef6679-1355-36c4-9b6c-14ff138bf0c8, sub=admin, aud=null, exp=Wed Jan 31 11:16:18 CET 2018, nbf=null, iat=Wed Jan 31 11:13:18 CET 2018, jti=null, typ=null, customClaims={qsh=711ed245693eeda3ce731855e4aebce21030be47117462aa87e46e45c774b397, context={"user":{"displayName":"Matthias Küspert","userKey":"admin","username":"admin"}}}]
2018-01-31 11:13:50.998 DEBUG 50711 --- [nio-3000-exec-5] c.a.c.s.i.a.j.JwtAuthenticationProvider : Canonical request for incoming JWT: CanonicalHttpServletRequest[method=POST,relativePath=/configuration,parameterMap=[tz -> (Europe/Berlin),loc -> (en-US),user_id -> (admin),user_key -> (admin),xdm_e -> (https://kuespert-dev.atlassian.net),xdm_c -> (channel-com.xqual.jira.jira-xstudio-connect-plugin__xstudio-integration-config-page),cp -> (),xdm_deprecated_addon_key_do_not_use -> (com.xqual.jira.jira-xstudio-connect-plugin),lic -> (none),cv -> (1.3.445),jwt -> (eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInFzaCI6IjcxMWVkMjQ1NjkzZWVkYTNjZTczMTg1NWU0YWViY2UyMTAzMGJlNDcxMTc0NjJhYTg3ZTQ2ZTQ1Yzc3NGIzOTciLCJpc3MiOiJmOGVmNjY3OS0xMzU1LTM2YzQtOWI2Yy0xNGZmMTM4YmYwYzgiLCJjb250ZXh0Ijp7InVzZXIiOnsidXNlcktleSI6ImFkbWluIiwidXNlcm5hbWUiOiJhZG1pbiIsImRpc3BsYXlOYW1lIjoiTWF0dGhpYXMgS8O8c3BlcnQifX0sImV4cCI6MTUxNzM5Mzc3OCwiaWF0IjoxNTE3MzkzNTk4fQ.EciutkU3B1pcH3WbXDysmn2mdVmfGsaZk1NMPC6MKSo,eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJjb20ueHF1YWwuamlyYS5qaXJhLXhzdHVkaW8tY29ubmVjdC1wbHVnaW4iLCJzdWIiOiJhZG1pbiIsImNsaWVudEtleSI6ImY4ZWY2Njc5LTEzNTUtMzZjNC05YjZjLTE0ZmYxMzhiZjBjOCIsImlzcyI6ImNvbS54cXVhbC5qaXJhLmppcmEteHN0dWRpby1jb25uZWN0LXBsdWdpbiIsImV4cCI6MTUxNzM5NDUwNiwiaWF0IjoxNTE3MzkzNjA2fQ.IfyA6-B1zLD7ScyNDjEgclXOKQnCnzrFXyf9p0mCIYg),issueTypes -> (Bug,New Feature),restUrl -> (http://209.177.145.128:8080/biot/api),webappUrl -> (https://209.177.145.128:8080/biot/plugins/jira),username -> (admin),password -> (xxxx),showInline -> (on),save -> (Save),]]
2018-01-31 11:13:51.129 ERROR 50711 --- [nio-3000-exec-5] c.a.c.s.i.a.j.JwtAuthenticationProvider : Expecting claim 'qsh' to have value '7af3e1dcb7647b82981d1d952b8eeb32fbd4d199e241e5e35eba4afe869914a1' but instead it has the value '711ed245693eeda3ce731855e4aebce21030be47117462aa87e46e45c774b397'
Building a showcase may last a bit, since I’m now at my main job - the plugin is just something I do by the side.
Okay, so the JWT being rejected was issued by Jira, not by your add-on.
The problem is that the form submission request contains two JWTs: one in the URL query string (/configuration?..&jwt…) and one in the request body.
When JwtAuthenticationFilter
can’t find an Authorization
header with a JWT, it tries to retrieve the JWT from the request parameters by calling ServletRequest#getParameter(String)
. And from what I can tell, that method seems to give preference to the query parameter.
So to avoid this problem, specify the action
of your <form>
explicitly to avoid including the iframe URL query-string.
Yes: this did the trick. Now the JWT is accepted by the backend.
Many thanks!
I am experiencing a similar problem. Successfully using JWT qsh from my plugin server making curl REST requests, BUT when Atlassian sends a request to my server, I try to match the qsh and I can’t. I have tried everything and am pulling my hair out (not much left anyway). To recap everything works fun except I fail to match the qsh on calls from Jira to my server.
Any tips most gratefully received.