How do I sign my JWT requests for the REST interface?

To answer your earlier question, the ‘tenant base url’ is https://testtablet.atlassian.net for JIRA and Log in with Atlassian account for Confluence.

I got a trivial add-on working with atlassian-jwt and I think I know what the issue was: we should be providing the addon key as the ‘clientKey’ parameter because that’s what JIRA and Confluence Connect expect the iss to be. Below is the listing for a minimal add-on (Python 2.7) that pings the REST api and prints the result to show that it was able to authenticate.

It listens on port 5000. You will need to provide a publicly-accessible https url (e.g. the url you get from running ngrok http 5000) as the first argument.

requirements.txt:

atlassian-jwt==1.6
click==6.7
Flask==0.12
itsdangerous==0.24
Jinja2==2.9.5
MarkupSafe==1.0
PyJWT==1.4.2
requests==2.13.0
Werkzeug==0.11.15
wheel==0.24.0

addon.py:

import sys

import atlassian_jwt
import requests
from flask import Flask, request, jsonify, redirect

ADDON_KEY = "simple-flask-addon"
clients = {}

if __name__ == '__main__':
    app = Flask(__name__)
    descriptor = {
        "key": ADDON_KEY,
        "baseUrl": sys.argv[1],
        "authentication": {"type": "jwt"},
        "scopes": ["READ"],
        "lifecycle": {
            "installed": "/register",
            "enabled": "/ping",
        },
    }


    class SimpleAuthenticator(atlassian_jwt.Authenticator):
        def get_shared_secret(self, client_key):
            return clients[client_key]['sharedSecret']


    auth = SimpleAuthenticator()


    @app.route('/', methods=['GET'])
    def redirect_to_descriptor():
        return redirect('/descriptor')


    @app.route('/descriptor', methods=['GET'])
    def get_descriptor():
        return jsonify(descriptor)


    @app.route('/register', methods=['POST'])
    def register():
        client = request.get_json()
        clients[client['clientKey']] = client
        return '', 204


    @app.route('/ping', methods=['POST'])
    def ping():
        client_key = auth.authenticate(request.method, request.url, request.headers)
        client = clients[client_key]
        ping_url = '/rest/api/latest/issue/TEST-2'
        jwt_authorization = 'JWT %s' % atlassian_jwt.encode_token('GET', ping_url, ADDON_KEY, client['sharedSecret'])
        result = requests.get(client['baseUrl'].rstrip('/') + ping_url, headers={'Authorization': jwt_authorization})
        result.raise_for_status()
        print '%s - %s' % (result.status_code, result.json())
        return '', 204


    app.run(debug=True)
8 Likes