Application Links exist to handle authentication when making calls between applications.

App links can be configured in one of three ways

  • OAuth

  • Trusted applications

  • Basic authentication

However only the first of these is currently recommended by Atlassian, and is the kind we will focus on.

Note that all of the examples provided below also work with Trusted applications.

OAuth comes in two flavours: OAuth authentication and OAuth with impersonation. Impersonation should only be used where the sets of users on both apps are the same.

If you can enable OAuth with impersonation you should do so, as it allows you to make requests from code on behalf of the user that invoked the function (eg event, workflow function etc), without any interaction on their behalf.

The following image shows the outbound configuration the source app, and the inbound configuration for the target app, when two-legged oauth with impersonation is enabled.

Configuration with 2 legged-oauth


If you create a new reciprocal app link, and check the box confirming that the set of users are the same on both apps, you will get the configuration above.

Making Requests as the current User

If you wish to make a remote REST request on behalf of the current user, you can do so using com.atlassian.applinks.api.ApplicationLink.createAuthenticatedRequestFactory(). The following example calls a JIRA endpoint that returns details of the user making the request, so is useful for experimenting.

This example should work calling JIRA from both Bitbucket Server and Confluence. To call another app you should change the endpoint, as this one exists only in JIRA. Note also that in JIRA you will get the ApplicationLinkService using ComponentAccessor rather than ComponentLocator.

Unresolved directive in content/common/interacting-with-other-apps-via-applinks.adoc - include::../bitbucket/src/test/resources/examples/bitbucket/authnz/SimpleRequest.groovy[tags=ex1]
1 get the primary JIRA application link - if you have multiple see discussion later
2 get the oauth provider
3 the response is JSON, so convert it to a Map
4 execute the request

You should see a log message like:

2016-05-05 10:15:34 [http-bio-8080-exec-10] DEBUG c.o.s.runner.ScriptRunnerImpl - Making the request as: admin

Making Requests as another User

That’s great, but let’s say you want you want to create a new page in Confluence on a JIRA transition. If the user executing the JIRA transition does not have permission to create a page, this will fail. You may well want this to happen, indeed it’s probably the safest course. But let’s say you want to create a Confluence space on a transition, perhaps as part of a provisioning process. If this is the case you will need to temporarily impersonate a user on the target system that has the create page or create space permission etc.

How you do that is unfortunately not standardised across applications, so what follows are examples for each application supported by ScriptRunner:

It’s advisable to create a user called for example: deployment, which has admin rights. You can create a password which can’t be used, so you will know whenever you see this user in the audit log, that these changes are the results of your integrations.

From Bitbucket Server

Unresolved directive in content/common/interacting-with-other-apps-via-applinks.adoc - include::../bitbucket/src/test/resources/examples/bitbucket/authnz/TempImpersonation.groovy[tags=ex1]

From Confluence

Unresolved directive in content/common/interacting-with-other-apps-via-applinks.adoc - include::../confluence/src/test/resources/examples/docs/authnz/TempImpersonation.groovy[tags=ex1]


Unresolved directive in content/common/interacting-with-other-apps-via-applinks.adoc - include::../jira/src/test/resources/examples/docs/authnz/TempImpersonation.groovy[tags=ex1]

Two-legged OAuth without impersonation

If you have different sets of users between your apps, you cannot use two-legged authentication with impersonation. The problem here is that user jbloggs on JIRA may actually refer to a different jbloggs on Confluence. Atlassian expresses this in their documentation as "users must have the same password", but I believe they mean that the user for any given ID should be the same person.

If you just have some a subset of users in one app that all exist in another app you should be OK using 2-legged with impersonation.

If not, your alternatives are:

  • specify a user on the target app that all remote requests via this link will execute as. However, as you can’t specify a user with admin rights this may not be useful

  • prompt the end-user to do the login dance, which will allow them to grant the source app to make requests to the target on their behalf.

This code sample focuses on doing the dance.

Unresolved directive in content/common/interacting-with-other-apps-via-applinks.adoc - include::../bitbucket/src/test/resources/examples/bitbucket/authnz/DoTheOAuthDance.groovy[tags=ex1]

Once the user has clicked the link which takes them to the page below, the code will proceed beyond the catch block.


The problem you may encounter is that there may not be any easy way to present this URL to the user in the web UI. In this case you could just fail the transition or whatever, or in JIRA, add a message in to the UI:

Unresolved directive in content/common/interacting-with-other-apps-via-applinks.adoc - include::../jira/src/test/resources/examples/docs/authnz/UserMessageExample.groovy[tags=ex1]

For how-to questions please ask on Atlassian Answers where there is a very active community. Adaptavist staff are also likely to respond there.

Ask a question about ScriptRunner for JIRA, for for Bitbucket Server, or for Confluence.