Skip to content

Instantly share code, notes, and snippets.

@haxwithaxe
Last active March 13, 2016 15:10
Show Gist options
  • Save haxwithaxe/118bec81c35369abee28 to your computer and use it in GitHub Desktop.
Save haxwithaxe/118bec81c35369abee28 to your computer and use it in GitHub Desktop.
Oauth with Jira: a tale of crappy documentation

The relavent documentation is (here)[https://bitbucket.org/atlassian_tutorial/atlassian-oauth-examples]. The example application info they provide is below. They did not use this in the example code for whatever reason. Consumer key: dpf43f3p2l4k3l03 Consumer name: OAuth Test Description: OAuth Test Example Public key: Consumer callback URL: http://<hostname where you're hosting this code>/auth

Included is a modified app.py. They had a test to demonstrate that you can't access an issue before oauth is setup and can after it is setup ... this doesn't work well if you have annonymous access enabled ... I removed the cute demo tests.

A note for those implementing client apps: Jira does not allow direct oauth user logins for the rest api. This example implements the linked application server.

import base64
import urlparse
from tlslite.utils import keyfactory
import oauth2 as oauth
JIRA_URL = 'http://myjirainstance.example/'
consumer_key = 'oauth-sample-consumer'
consumer_secret = 'dont_care'
request_token_url = '%s/plugins/servlet/oauth/request-token'
access_token_url = '%s/plugins/servlet/oauth/access-token'
authorize_url = '%s/plugins/servlet/oauth/authorize'
class SignatureMethod_RSA_SHA1(oauth.SignatureMethod):
name = 'RSA-SHA1'
def signing_base(self, request, consumer, token):
if not hasattr(request, 'normalized_url') or request.normalized_url is None:
raise ValueError("Base URL for request is not set.")
sig = (
oauth.escape(request.method),
oauth.escape(request.normalized_url),
oauth.escape(request.get_normalized_parameters()),
)
key = '%s&' % oauth.escape(consumer.secret)
if token:
key += oauth.escape(token.secret)
raw = '&'.join(sig)
return key, raw
def sign(self, request, consumer, token):
"""Builds the base signature string."""
key, raw = self.signing_base(request, consumer, token)
with open('../rsa.pem', 'r') as f:
data = f.read()
privateKeyString = data.strip()
privatekey = keyfactory.parsePrivateKey(privateKeyString)
signature = privatekey.hashAndSign(raw)
return base64.b64encode(signature)
def oauth_dance():
consumer = oauth.Consumer(consumer_key, consumer_secret)
client = oauth.Client(consumer)
consumer = oauth.Consumer(consumer_key, consumer_secret)
client = oauth.Client(consumer)
client.set_signature_method(SignatureMethod_RSA_SHA1())
# Step 1: Get a request token. This is a temporary token that is used for
# having the user authorize an access token and to sign the request to obtain
# said access token.
resp, content = client.request(request_token_url % JIRA_URL, "POST")
if resp['status'] != '200':
raise Exception("Invalid response %s: %s" % (resp['status'], content))
request_token = dict(urlparse.parse_qsl(content))
print('''Request Token:
- oauth_token = %s
- oauth_token_secret = %s''' % (request_token['oauth_token'], request_token['oauth_token_secret'])
# Step 2: Redirect to the provider. Since this is a CLI script we do not
# redirect. In a web application you would redirect the user to the URL
# below.
print("Go to the following link in your browser:\n%s?oauth_token=%s" % (authorize_url % (JIRA_URL, request_token['oauth_token'])))
# After the user has granted access to you, the consumer, the provider will
# redirect you to whatever URL you have told them to redirect to. You can
# usually define this in the oauth_callback argument as well.
accepted = 'n'
while accepted.lower() == 'n':
accepted = raw_input('Have you authorized me? (y/n) ')
# oauth_verifier = raw_input('What is the PIN? ')
# Step 3: Once the consumer has redirected the user back to the oauth_callback
# URL you can request the access token the user has approved. You use the
# request token to sign this request. After this is done you throw away the
# request token and use the access token returned. You should store this
# access token somewhere safe, like a database, for future use.
token = oauth.Token(request_token['oauth_token'],
request_token['oauth_token_secret'])
#token.set_verifier(oauth_verifier)
client = oauth.Client(consumer, token)
client.set_signature_method(SignatureMethod_RSA_SHA1())
resp, content = client.request(access_token_url % JIRA_URL, "POST")
access_token = dict(urlparse.parse_qsl(content))
print('''Access Token:
- oauth_token = %s
- oauth_token_secret = %s''' % (access_token['oauth_token'], access_token['oauth_token_secret'])
)
print("\nYou may now access protected resources using the access tokens above.\n")
# Now lets try to access the same issue again with the access token. We should get a 200!
accessToken = oauth.Token(access_token['oauth_token'], access_token['oauth_token_secret'])
client = oauth.Client(consumer, accessToken)
client.set_signature_method(SignatureMethod_RSA_SHA1())
oauth_dance()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment