Last updatedAug 19, 2019

Authentication for Connect apps

Atlassian Connect uses a technology called JWT (JSON Web Token) to authenticate apps. The Connect app and the host product exchange a security context when the app is installed. This context contains a shared secret used to create and validate JWT tokens for use in API calls. All instances of your app use the same shared secret.

The use of JWT tokens guarantees that:

  • The Atlassian product can verify it is talking to the app, and vice versa (authenticity).
  • None of the query parameters of the HTTP request, nor the path (excluding the context path), nor the HTTP method, were altered in transit (integrity).

The Atlassian frameworks include tools for creating and using JWT tokens easily.

Authentication basics

Here's how to use authentication in your app:

  1. In the app descriptor, declare that the app uses JWT as the authentication mechanism.
  2. Implement an installation callback endpoint and add a reference to it in the app descriptor.
  3. When the installation callback is called at app install time, store the security context that is passed in.
  4. Use the security context to validate incoming requests and sign outgoing requests.

About the app descriptor

To enable your Atlassian Connect app to authenticate securely with the host Atlassian product, make sure the following elements are in the app descriptor:

  • authentication:type: the authentication type (always jwt)
  • lifecycle:installed: a callback endpoint to call at installation time

For example:

1
2
3
4
5
6
7
8
9
10
11
{
    "baseUrl": "http://localhost:3000",
    "key": "atlassian-connect-app",
    "authentication": {
        "type": "jwt"
    },
    "lifecycle": {
        "installed": "/app-installed-callback"
    },
    "modules": {} // etc
}

Upon successful registration, the app must return either a 200 OK or 204 No Content response code. Otherwise, the operation will fail and the installation will be marked as incomplete.

Installation data

When the app is installed, the Atlassian product passes your callback a security context that contains important information that you will need to store in your app in order to sign and verify future requests.

For details on the contents of the payload, please see the lifecycle attribute documentation.

Your installation callback must execute synchronously.

Making a service call

When communicating server-to-server with the Atlassian host product your app must include a JWT token to access protected resources. This includes most of the REST APIs. You can use JWT libraries to construct a token that identifies your app, identifies the query, specifies the token's expiration time, and allows the receiver to verify that the token was genuinely constructed by your app.

Query string example:

1
GET https://<my-dev-environment>.atlassian.net/jira/rest/api/2/issue/AC-1.json?jwt=<jwt-token>

Headers example:

1
2
POST https://<my-dev-environment>.atlassian.net/jira/rest/api/2/issue/AC-1/attachments
"Authorization" header value: "JWT <jwt-token>"

For more details on how to create a JWT token, see Creating a JWT Token.

Validating incoming requests

All incoming requests from an Atlassian product to your service should check for the JWT, which needs to be decoded and verified. In particular, the verification should:

  1. Extract the JWT token from the request's jwt query parameter or the authorization header.
  2. Decode the JWT token without verification. This gives you a header JSON object, a claims JSON object, and a signature.
  3. Extract the issuer (iss) claim from the decoded, unverified claims object. This is the clientKey for the tenant - an identifier for the Atlassian product making the call, which should have been stored by the app as part of the installation handshake.
  4. Look up the sharedSecret for the clientKey, as stored by the app during the installation handshake
  5. Verify the signature with the sharedSecret and the algorithm specified in the header's alg field. This should be the HS256 algorithm.
  6. Verify the query has not been tampered by Creating a query hash and comparing it against the qsh claim on the verified token.
  7. Verify standard claims if present. Issuers include these to help you ensure that tokens you receive are used according to the intentions of the issuer and with the best possible results.

These steps must be executed before processing the request, and the request must be rejected if any of these steps fail.

For more details on how to decode and validate a JWT token, see Decoding and verifying a JWT and the Atlassian-supported claims that you need to validate.

Signing outgoing requests

When JWT authentication is used the lifecycle callbacks contain a JWT token signed with a shared secret. This signed token is placed inside of the Authorization HTTP header of the lifecycle POST request. When your app is first installed, the shared secret is exchanged for the first time. All instances of your app use the same shared secret. It is available to sign callbacks on subsequent installations.

The best way to see these JWT tokens on your lifecycle events is to use the Connect inspector to create a temporary app, install it in your cloud development environment and watch the lifecycle events roll in. This will give you a good understanding of the lifecycle (and Webhook) flow.

Use caseShared secret used to sign
First installNone; no JWT token. Because there was no previous shared secret the recipient cannot validate a JWT token. This means that you should anticipate that there will be no Authorization header present.
Second and subsequent installsThe shared secret sent in the preceding installed callback.
Uninstall, enable & disableThe shared secret sent in the preceding installed callback.
First install after being uninstalledThe shared secret sent in the preceding installed callback. This allows apps to allow the new installation to access previous tenant data (if any exists).
A valid signature demonstrates that the sender is in possession of the shared secret from when the old tenant data was accessed.

JWT flows

These diagrams illustrate communication between your app and the host product at various common points.

Making a service call with JWT

To call an API exposed by an Atlassian product, the app must add a valid JWT token to the request.

Making a service call with user impersonation

To call an API exposed by an Atlassian product and initiate a service on behalf of a user, the app must add a valid OAuth 2.0 access token to the request. To get an OAuth 2.0 access token, the app exchanges a signed JWT for an OAuth 2.0 access token through the Atlassian authorization server.

Serving a request

When an Atlassian product calls an API exposed by the app, it is the app's responsibility to validate the JWT token, using the security context provided during the installation handshake.