When the publicKey gets rotated it will always be linked to a new unique kid which makes it unlikely to return a different key. If the addon server had already received a JWT token with a kid that means the public key is already available in https://connect-install-keys.atlassian.com/. However, the worst case scenario will be this service becoming unavailable right after Jira/Confluence has successfully signed the token and sent the request to the lifecycle event.
what is the customer experience when we reject an installation because the key we have is not correct/available etc?
In this case, the app server will respond with 4xx status code and customer gets and error saying The app host returned HTTP response code 4xx when we tried to contact it during installation. Please try again later or contact the app vendor.
Previously, this issue was being reported when shared secret gotten out of sync and needed to manually resolve the issue. But if CDN somehow fails to respond in future, customer can retry without having to contact us or the app Vendors.
is there actual monitoring (not integration testing) which is driving installation and uninstallation of apps outside of the Atlassian AWS infrastructure
We have a service running series of app install/uninstall scenarios almost every minute on production and our team will investigate every time we notice any failures.
Hi @OfirNir, Thanks for reporting this issue.
We have patched a new version to fix this os dependent problem. Could you please check with ACSB v2.2.1 ? It should be available from maven central within a couple of hours
@HanjooSong
If every key rotation generates a new kid, it is actually ok to cache the key, right?
Just want to clarify as it is the opposite what was initially posted.
The comments in this thread indicate that addon.authenticateInstall() can be used for the install and uninstall routes. The latest docs imply, however, that all lifecycle methods are similarly authenticated: āLifecycle request contains a JWT token signed with private key [ā¦]ā
Empirical evidence (and the top of this post) suggest that only the install and uninstall hooks are covered, and not others (ie. enabled/disabled). Can you confirm, and if so, update the docs?
Can you elaborate on this please? When we add "signed-install": "enabled" to config.json, the /installed-route behaviour seems unchanged. Adding "apiMigrations": { "signed-install": true } to the descriptor seems to take the new authentication into use, and is causing not problems for us.
Our app serves both Jira and Confluence so we have two addons. We have two different hosts (mapping to the same server) to be able to serve the correct descriptor. (e.g. jira.refined.com and confluence.refined.com)
Creating an ACE addon registers a handler for /installedPOST requests and this handler also authenticates the request. The problem is, that the new authentication method requires addon.config.localBaseUrl() to match the request host. In our setup this can cause a situation where the user is installing our app to Confluence, but the Jira addon also tries to verify the installation, causing an error 'Authentication verification error (401): JWT claim did not contain the correct audience (iss) claim'
App upgrade hooks from hosts also appear to have asymmetric RS256 signatures, however the above docs donāt make this clear (unless Iām reading it wrong).
@Bentley pinging you because this is the type of stale topic that should not be stale. Itās noteworthy that the answers to simple questions did continue a bit longer but the more ādifficultā questions from myself and John Mort have been actively ignored
Iāve tested updating ACE to v7.3.0 and adding "signed-install": "enable" to my config and it seems to work locally.
Will this continue to work? Do I need to do anything special to the routes managed by ACE as Iām not doing anything custom (ie add addon.authenticate() ect)?
Cheers
EDIT: I just realised /installed, /uninstalled and /enabled are all POSTs not GETs and arenāt being referred to anyway
Hi @ekaukonen .
We are running a custom implementation of Atlassian Connect framework based on Play 2.
We compared Spring Boot implementation of asymmetric JWT and example implementation from atlassian docs (part āVerifying a asymmetric JWT token for install callbacksā) .
Spring Boot implementation checks both JWT signature and all the standard and non standard claims including Audience claim (com.atlassian.connect.spring.internal.jwt.AbstractJwtReader#readAndVerify ). But as per code snippets from the atlassian docs (part āVerifying a asymmetric JWT token for install callbacksā) it is recommended to check the JWT signature and the Audience claim (there is no verification of standard and non-standard claims in the example code snippets). Seems like we need to verify all the claims of an asymmetric JWT the same way as it is implemented in ACSB.
Could you please clarify, do we need to perform all claims (not only aud but all the standard claims and qsh ) checks during an asymmetric JWT token verification and why claims checks skipped in code snippets from atlassian docs?
Iām also confused by this currently. It would seem that at least the /enabled hook still uses the old JWT structure even with the "signed-install": true
Hi @aorlov. Yes, you need to verify all claims including audience. I do agree with your confusion around the examples from the docs, it emphasises that audience needs to be checked but not much about other required claims. I will update the docs to make this more clear. Thanks!
Hi @ErkkiLepre. Iād be happy to take a look at this issue if you can create a DEVHELP ticket and provide more details like your config.json and the descriptor configurations.
And also for your question related to the audience claims, I will keep you updated after adding support for list of aud claims.