atlassian-jwt 3.0.0
JSON web token: pyjwt plus Atlassian query-string-hash claim
Keywords: jwt,json,web,token,pyjwt,atlassian,connect,addon,query,string,hash,qsh

atlassian-jwt (Python)
======================

`codebeat
badge <https://codebeat.co/projects/bitbucket-org-atlassian-atlassian-jwt-py/ratings>`__

`JSON Web Token <https://jwt.io/>`__ (JWT) authentication and encoding
library for Python 2 and 3. Extends
`pyjwt <https://github.com/jpadilla/pyjwt>`__ to include Atlassian
Connect’s custom `query string
hash <https://developer.atlassian.com/blog/2015/01/understanding-jwt/>`__
(qsh) claim.

This package is on `pypi <https://pypi.python.org/pypi/atlassian-jwt>`__
so you can use pip to install it

::

   pip install atlassian-jwt

Tenant information
------------------

This package makes references to Atlassian Connect’s `tenant information
data
structure <https://developer.atlassian.com/static/connect/docs/latest/modules/lifecycle.html>`__.
Specfically the ``clientKey`` and ``sharedSecret`` fields are used when
encoding a JWT token. Here is an example of the complete tenant
information data structure as is passed to a Connect Addon with the
``installed`` lifecycle callback.

::

   {
     "key": "installed-addon-key",
     "clientKey": "unique-client-identifier",
     "publicKey": "MIGf....ZRWzwIDAQAB",
     "sharedSecret": "a-secret-key-not-to-be-lost",
     "serverVersion": "server-version",
     "pluginsVersion": "version-of-connect",
     "baseUrl": "http://example.atlassian.net",
     "productType": "jira",
     "description": "Atlassian JIRA at https://example.atlassian.net",
     "serviceEntitlementNumber": "SEN-number",
     "eventType": "installed"
   }

Where

-  *clientKey* is an identifying key for the Atlassian product instance
   that the add-on was installed into.
-  *sharedSecret* is the string that should be used to sign outgoing JWT
   tokens and validate incoming JWT tokens.

Authentication
--------------

This package provides an abstract base class that can be subclassed to
provide authentication to an Atlassian Connect Addon. Here is an example
of that use

::

   import atlassian_jwt

   class MyAddon(atlassian_jwt.Authenticator):
       def __init__(self, tenant_info_store):
           super(MyAddon, self).__init__()
           self.tenant_info_store = tenant_info_store

       def get_shared_secret(self, client_key):
           tenant_info = self.tenant_info_store.get(client_key)
           return tenant_info['sharedSecret']

   my_auth = MyAddon(tenant_info_store)
   try:
       client_key, claims = my_auth.authenticate(http_method, url, headers)
       # authentication succeeded
   except atlassian_jwt.DecodeError:
       # authentication failed
       pass

Encoding
--------

Atlassian Connect Addon can make API calls back to the host application.
These API calls include a JWT token for authentication. This package
provides an ``encode_token`` function to do this work. Here is an
example of its use

::

   import atlassian_jwt

   token = atlassian_jwt.encode_token(http_method, url, **tenant_info)
   headers = {'Authorization': 'JWT {}'.format(token)}

Understanding JWT for Atlassian Connect
---------------------------------------

-  `Understanding JWT for Atlassian
   Connect <https://developer.atlassian.com/blog/2015/01/understanding-jwt/>`__
-  `Understanding
   JWT <https://developer.atlassian.com/static/connect/docs/latest/concepts/understanding-jwt.html>`__
-  `Creating a query string
   hash <https://developer.atlassian.com/static/connect/docs/latest/concepts/understanding-jwt.html#qsh>`__

Running the tests
-----------------

::

   pip3.8 install -e . && pip3.8 install -r requirements.txt && python3.8 -m pytest