Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Atlassian Connect. How to use an JIRA authentication header?

moskrc January 10, 2014

Help me please. I'm working on my first JIRA plugin using Atlassian Connect (my platform is django/python) and having a real hard time figuring out how to do a REST requests to JIRA on behalf of the current JIRA user. I want to use jira-python, but it required auth_token and auth_token_secret, but I don't have it.

Here's my authentication header (JIRA has sent it to me when an user click on the link of my addon every time):

[09/Jan/2014 20:47:52] "GET /app/?

?oauth_version=1.0
&user_id=admin

&oauth_signature_method=RSA-SHA1
&oauth_nonce=1389199973324143000
&oauth_consumer_key=jira%3E045e3efe-711a-4aca-9fbb-dc62fa62fb03
&oauth_timestamp=1389199973
&oauth_signature=XXXXXXX

&user_key=admin
&loc=ru-RU
&lic=none
&cp=%2Fjira
&tz=Europe%2FMoscow
&xdm_e=http%3A%2F%2Flocalhost%3A2990
&xdm_c=channel-servlet-general
&xdm_p=1
HTTP/1.1" 200 3540

How can I use these parameters to do REST requests from the current JIRA user?

Any suggestions?

Thanks

11 answers

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

1 vote
seb
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
January 11, 2014

Hi Vitaliy,

Can you please post your atlassian-plugin.xml descriptor?

For what it's worth, we've just deprecated the XML + OAuth paths for Atlassian Connect. I would recommend looking at our new documentation portal:

https://developer.atlassian.com/static/connect/docs/

Specifically, look at the what's new page:

https://developer.atlassian.com/static/connect/docs/guides/whats-new.html

And the documentation for implementing Authentication with JWT:

https://developer.atlassian.com/static/connect/docs/concepts/authentication.html

We have responded to significant feedback that the OAuth 1.0 spec is very hard to implement and get right. As such, we are replacing it with JWT, a much simpler and easier to undestand spec. Our new docs provide a much more thorough set of guides and tutorials for you.

Regards,

Seb

0 votes
Kim Poulsen
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 14, 2014

Did you visit this link? We setup OAuth using python-jira in a couple of hours. I have commented on that page what our pitfalls were so that others won't fall in to the same ones. (It is the second comment)

https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Example+-+OAuth+authentication

0 votes
moskrc January 12, 2014

Give me a link please.

seb
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
January 13, 2014

There is no link to give. Atlassian Connect tries to make as many rest endpoints available as possible. If you cannot access one, this is most likely an oversight and you should raise an issue at https://ecosystem.atlassian.net/browse/AC

0 votes
moskrc January 11, 2014

Tell me where I can find all available URLs for Atlassian Connect please.

0 votes
moskrc January 11, 2014

No Success :(

atlas-run-standalone --product jira --version 6.2-OD-05-4 --bundled-plugins com.atlassian.plugins:atlassian-connect-plugin:1.0-m25,com.atlassian.jwt:jwt-plugin:1.0-m6,com.atlassian.webhooks:atlassian-webhooks-plugin:0.17.3,com.atlassian.httpclient:atlassian-httpclient-plugin:0.17.1,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.14.2,com.atlassian.bundles:json-schema-validator-atlassian-bundle:1.0-m0 --jvmargs -Datlassian.upm.on.demand=true

Error 401 every time..

In the request content I see:

<script type="text/javascript" src="/jira/rest/api/1.0/shortcuts/6207/2b82d97bab903dcadc2da7d63304ba8c/shortcuts.js"></script>

    <meta name="application-name" content="JIRA" data-name="jira" data-version="6.2-OD-05-4">

</head>

<body id="jira" class="aui-layout aui-style-default page-type-message"  data-version="6.2-OD-05-4" >

    <div class="aui-page-panel"><div class="aui-page-panel-inner">

            <section class="aui-page-panel-content">

                    <header class="aui-page-header"><div class="aui-page-header-inner">

                            <div class="aui-page-header-main">

                                    <h1>Unauthorized (401)</h1>

                                </div><!-- .aui-page-header-main -->

                        </div><!-- .aui-page-header-inner --></header><!-- .aui-page-header -->

                    <div class="aui-message warning">

                            <p>Encountered a <code>"401 - Unauthorized"</code> error while loading this page.</p>

                            <p><a href="/jira/secure/MyJiraHome.jspa">Go to JIRA home</a></p>

                        <span class="aui-icon icon-warning"></span></div>

                </section><!-- .aui-page-panel-content -->

        </div><!-- .aui-page-panel-inner --></div><!-- .aui-page-panel -->

</body>

</html>

seb
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
January 11, 2014

The reason is that the "rest/api/2/myself" url is not whitelisted for use in Atlassian Connect. If you would like to use it, please raise an issue at http://ecosystem.atlassian.net/browse/AC

Thanks

moskrc January 11, 2014

Thanks. Where I can see all available URLs?

0 votes
moskrc January 11, 2014

I have no success..

It seems to me that the JWT authorization is not works.. I got "401" every time.

Look at this please, where I'm wrong? Or it's a bug?

Python code:

import jwt
import hashlib
import datetime
import calendar
import requests


def send_request(incoming_jwt, url, method, params={}):
    print 'INCOMING JWT (FROM ATLASSIAN)'
    print incoming_jwt
    print ''

    jwt_decoded = jwt.decode(incoming_jwt, verify=False)

    print 'DECODED JWT FROM ATLASSIAN'
    print jwt_decoded
    print ''

    jwt_model = JWT.objects.get(client_key=jwt_decoded['iss'])

    full_url = jwt_model.base_url + url

    print 'FULL URL'
    print full_url
    print ''

    qsh = '%(method)s&%(path)s&' % {'method': method.upper(), 'path': urlparse.urlparse(full_url).path}

    print 'QSH'
    print qsh
    print ''

    iat = datetime.datetime.utcnow()
    exp = iat + datetime.timedelta(minutes=3)

    jwt_payload = {
        'iss': jwt_model.client_key,
        'iat': calendar.timegm(iat.utctimetuple()),
        'exp': calendar.timegm(exp.utctimetuple()),
        'qsh': hashlib.sha256(qsh).hexdigest(),
        'sub': jwt_decoded['sub']
    }

    print 'NEW PAYLOAD'
    print jwt_payload
    print ''

    new_jwt = jwt.encode(jwt_payload, jwt_model.shared_secret)

    print 'NEW JWT'
    print new_jwt
    print ''

    headers = {'Authorization': 'JWT %s' % new_jwt, 'Content-Type': 'application/json'}

    print 'MAKE REQUEST...'
    r = requests.get(full_url, params={'jwt': new_jwt}, headers=headers)
    print 'DONE'

    print '-' * 100
    print 'ANSWER'
    print '-' * 100
    print 'REQUEST STATUS CODE'
    print '-' * 100
    print r.status_code
    print '\n'
    print 'ADDITIONAL INFO'
    print '.' * 100
    print 'REQUEST HEADERS'
    print r.request.headers
    print 'RESPONSE HEADERS'
    print r.headers
    print 'REQUEST URL'
    print r.url

    print '.' * 100

    try:
        return r.json()
    except Exception as e:
        return {}


print 'TRY TO SEND REQUEST'
print '-------------------'
print '\n'
print send_request(request.GET.get('jwt'), '/rest/api/2/myself', 'GET', {})

And it's output:

TRY TO SEND REQUEST
-------------------


INCOMING JWT (FROM ATLASSIAN)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEzODk1MjA5MDUsInN1YiI6ImFkbWluIiwiaXNzIjoiamlyYTo4OWQ0OTFiYS1jYzA2LTRkZDMtYWQ1ZS0xMGRiZjg4MjBjZWUiLCJxc2giOiIwMTBiODkxYjYyYWEzNzU3OTY5ZmNkNGFiNjQ0ZDlkOTNkNWRhZDlhYjVmNTQ1ZWZiNTM2Njc5MzQ1OWVhNjQ4IiwiaWF0IjoxMzg5NTIwNzI1fQ.JqkPnzH32csHrHpmMj_mnufPYLhzHS4HgGAGWDabqH0

DECODED JWT FROM ATLASSIAN
{u'iss': u'jira:89d491ba-cc06-4dd3-ad5e-10dbf8820cee', u'iat': 1389520725, u'qsh': u'010b891b62aa3757969fcd4ab644d9d93d5dad9ab5f545efb5366793459ea648', u'sub': u'admin', u'exp': 1389520905}

FULL URL
http://localhost:2990/jira/rest/api/2/myself

QSH
GET&/jira/rest/api/2/myself&

NEW PAYLOAD
{'iss': u'jira:89d491ba-cc06-4dd3-ad5e-10dbf8820cee', 'iat': 1389520731, 'qsh': '02ea14e8eaf913b046969d8900cef66ad251394a2c5dd57f8fc9ee187780e69c', 'sub': u'admin', 'exp': 1389520911}

NEW JWT
eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiamlyYTo4OWQ0OTFiYS1jYzA2LTRkZDMtYWQ1ZS0xMGRiZjg4MjBjZWUiLCAiaWF0IjogMTM4OTUyMDczMSwgInFzaCI6ICIwMmVhMTRlOGVhZjkxM2IwNDY5NjlkODkwMGNlZjY2YWQyNTEzOTRhMmM1ZGQ1N2Y4ZmM5ZWUxODc3ODBlNjljIiwgInN1YiI6ICJhZG1pbiIsICJleHAiOiAxMzg5NTIwOTExfQ.9dFa_jR9TR6XTBi68KSTDqpLFSCzU7C47W_dBnO75Zc

MAKE REQUEST...
DONE
----------------------------------------------------------------------------------------------------
ANSWER
----------------------------------------------------------------------------------------------------
REQUEST STATUS CODE
----------------------------------------------------------------------------------------------------
401


ADDITIONAL INFO
....................................................................................................
REQUEST HEADERS
CaseInsensitiveDict({'Authorization': 'JWT eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiamlyYTo4OWQ0OTFiYS1jYzA2LTRkZDMtYWQ1ZS0xMGRiZjg4MjBjZWUiLCAiaWF0IjogMTM4OTUyMDczMSwgInFzaCI6ICIwMmVhMTRlOGVhZjkxM2IwNDY5NjlkODkwMGNlZjY2YWQyNTEzOTRhMmM1ZGQ1N2Y4ZmM5ZWUxODc3ODBlNjljIiwgInN1YiI6ICJhZG1pbiIsICJleHAiOiAxMzg5NTIwOTExfQ.9dFa_jR9TR6XTBi68KSTDqpLFSCzU7C47W_dBnO75Zc', 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip, deflate, compress', 'Accept': '*/*', 'User-Agent': 'python-requests/2.2.0 CPython/2.7.6 Darwin/13.0.0'})
RESPONSE HEADERS
CaseInsensitiveDict({'x-content-type-options': 'nosniff', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=985234C0149A215E9B82A9E51F6060DF; Path=/jira/; HttpOnly', 'server': 'Apache-Coyote/1.1', 'date': 'Sun, 12 Jan 2014 09:58:51 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
REQUEST URL
http://localhost:2990/jira/rest/api/2/myself?jwt=eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiamlyYTo4OWQ0OTFiYS1jYzA2LTRkZDMtYWQ1ZS0xMGRiZjg4MjBjZWUiLCAiaWF0IjogMTM4OTUyMDczMSwgInFzaCI6ICIwMmVhMTRlOGVhZjkxM2IwNDY5NjlkODkwMGNlZjY2YWQyNTEzOTRhMmM1ZGQ1N2Y4ZmM5ZWUxODc3ODBlNjljIiwgInN1YiI6ICJhZG1pbiIsICJleHAiOiAxMzg5NTIwOTExfQ.9dFa_jR9TR6XTBi68KSTDqpLFSCzU7C47W_dBnO75Zc
....................................................................................................

What is it?

Thanks

seb
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
January 11, 2014

Try and increase the version of the jwt-plugin to 1.0-m6. We fixed this bug and haven't updated our docs just yet.

Thanks!

0 votes
moskrc January 11, 2014

Ouh... Thank you very much!!! It's works!

0 votes
moskrc January 11, 2014

Hi Seb,

Thanks, I rewriting the project to JWT and have a problem: I do not get that what is described in the documentation or I have an error with documentation. Look at this:

The lifecycle:installed property is a url which is synchronously called by the Atlassian application when the add-on is installed. The request contains a payload with important tenant information that you will need to store in your add-on in order to sign and verify future requests. The payload contains the following attributes:

{

    "key": "atlassian-connect-jira-addon-jwt",

    "clientKey": "1234567890",

    "publicKey": "MIGf....ZRWzwIDAQAB",

    "sharedSecret": "1ad6f705-fe0b-4111-9551-7ce5d81d2884",

    "baseUrl": "http://storm.dyn.syd.atlassian.com:2990/jira",

    "productType": "jira",

    "eventType": "installed"

}

But I get only:

[11/Jan/2014 22:35:00] "POST /addon/installed/?user_key=admin HTTP/1.1" 200 2
And POST parameters are empty. Just {}.

My "JSON":

{
    "name": "People Addon",
    "description": "Atlassian Connect add-on",
    "key": "x_people_addon",
    "baseUrl": "http://localhost:8000",
    "vendor": {
        "name": "My Organization, Inc",
        "url": "https://developer.atlassian.com"
    },
    "version": "1.0",
    "authentication": {
        "type": "jwt"
    },
    "lifecycle": {
        "installed": "/addon/installed/"
    },
    "modules": {
        "generalPages": [
            {
                "url": "/addon/",
                "name": {
                    "value": "Click Me"
                }
            }
        ]
    }
}

I run JIRA OnDemand:

$atlas-run-standalone --product jira --version 6.2-OD-05-4 --bundled-plugins com.atlassian.plugins:atlassian-connect-plugin:1.0-m25,com.atlassian.jwt:jwt-plugin:1.0-m3,com.atlassian.webhooks:atlassian-webhooks-plugin:0.17.3,com.atlassian.httpclient:atlassian-httpclient-plugin:0.17.1,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.14.2,com.atlassian.bundles:json-schema-validator-atlassian-bundle:1.0-m0 --jvmargs -Datlassian.upm.on.demand=true

Why I didn't get correct JWT payload?

Vitaliy

seb
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
January 11, 2014

Your descriptor json file looks fine. Have you inspected the body of the request to "/addon/installed" ?

0 votes
moskrc January 11, 2014

Hi Seb,

Thanks, I rewriting the project to JWT and have a problem: I do not get that what is described in the documentation or I have an error with documentation. Look at this:

The lifecycle:installed property is a url which is synchronously called by the Atlassian application when the add-on is installed. The request contains a payload with important tenant information that you will need to store in your add-on in order to sign and verify future requests. The payload contains the following attributes:

{

    "key": "atlassian-connect-jira-addon-jwt",

    "clientKey": "1234567890",

    "publicKey": "MIGf....ZRWzwIDAQAB",

    "sharedSecret": "1ad6f705-fe0b-4111-9551-7ce5d81d2884",

    "baseUrl": "http://storm.dyn.syd.atlassian.com:2990/jira",

    "productType": "jira",

    "eventType": "installed"

}

But I get only:

[11/Jan/2014 22:35:00] "POST /addon/installed/?user_key=admin HTTP/1.1" 200 2
And POST parameters are empty. Just {}.

My "JSON":

{
    "name": "People Addon",
    "description": "Atlassian Connect add-on",
    "key": "x_people_addon",
    "baseUrl": "http://localhost:8000",
    "vendor": {
        "name": "My Organization, Inc",
        "url": "https://developer.atlassian.com"
    },
    "version": "1.0",
    "authentication": {
        "type": "jwt"
    },
    "lifecycle": {
        "installed": "/addon/installed/"
    },
    "modules": {
        "generalPages": [
            {
                "url": "/addon/",
                "name": {
                    "value": "Click Me"
                }
            }
        ]
    }
}

I run JIRA OnDemand:

$atlas-run-standalone --product jira --version 6.2-OD-05-4 --bundled-plugins com.atlassian.plugins:atlassian-connect-plugin:1.0-m25,com.atlassian.jwt:jwt-plugin:1.0-m3,com.atlassian.webhooks:atlassian-webhooks-plugin:0.17.3,com.atlassian.httpclient:atlassian-httpclient-plugin:0.17.1,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.14.2,com.atlassian.bundles:json-schema-validator-atlassian-bundle:1.0-m0 --jvmargs -Datlassian.upm.on.demand=true

Why I didn't get correct JWT payload?

Vitaliy

0 votes
moskrc January 10, 2014

I got Request Token, it's ok, but when I try to get Auth Token - I got an error:

{'oauth_problem': 'permission_unknown'}

What is it?

0 votes
moskrc January 10, 2014

I spent two days .. I have no success so far. Please describe the algorithm, what should I do to get access_token please.

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

TAGS
AUG Leaders

Atlassian Community Events