[Data Residency] Is there a way for us to identify if a data residency hook request is valid from JIRA's migration service


Is there a way for us to identify if a data residency hook request is valid from JIRA’s migration service? We are trying to avoid anonymous requests from anyone who knows the hook APIs (through API fetch from 3rd party app like Postman).

For issue webhooks, there is this user_agent=“Atlassian Webhook HTTP Client” header. Is there anything similar to this for data residency hooks or another way for us to check and limit the request to only those coming from JIRA?

Also, as checked in https://ip-ranges.atlassian.com , the IP ranges can only be filtered by the specific product and connection direction. So we were wondering if there is a specific list of IP range/s assigned to JIRA migration service?

Reference IP addresses and domains for Atlassian cloud products | Atlassian Support

1 Like


Like the normal requests from atlassian, the requests from the migration service have a JWT token that is signed with the shared secret. If the JWT token is valid, it’s coming from Atlassian. A user agent is just a header, so you should not trust that for authentication.

Cheers, Fabian

Hi, thank you for your reply. We’re already authenticating all our requests with JWT. Is there any indicator from the JWT that it’s from a migration service?

The problem is that, these data residency hooks (/start, /schedule, etc) can easily be accessed/triggered through third party apps like Postman as long as you provide the correct Authentication and request body/params, which is what we’re trying to limit. We wanted to make sure that the request is only triggered by the migration service.

1 Like

from my understanding:

The JWT that you are receiving contains a qsh, which is a hash that contains the URL that is accessed. Since a jwt is cryptographically signed with the shared secret (that hopefully only you and atlassian know). This ensures that only with a valid JWT signed by Atlassian for this specific endpoint, the endpoint is callable.

The only exception here are tokens that you can get with AP.context.getToken(). These tokens are not using a qsh, so that they can work against all endpoints. However, you can recognize these tokens by checking if the qsh value of your JWT equals context-qsh. However, context-qsh tokens should never be accepted on lifecycle endpoints.

So to summarize: JWT tokens with a qsh field other than context-qsh that pass the validation are coming from atlassian, and JWT tokens that have context-qsh as qsh value should never be accepted on lifecycle endpoints.

You can read more about this stuff in the connect jwt documentation: https://developer.atlassian.com/cloud/jira/platform/understanding-jwt-for-connect-apps/

Note that I’m just another developer, and not a Atlassian.:slight_smile:


Thank you for the further explanation :slightly_smiling_face: we will try your suggestion.


Turns out that we only need to remove @ContextJwt from our controller. :grinning:

1 Like