Skip to content

Instantly share code, notes, and snippets.

@artizirk
Last active February 4, 2020 15:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artizirk/538619d4a654ada9a01f3bd1670a6fa6 to your computer and use it in GitHub Desktop.
Save artizirk/538619d4a654ada9a01f3bd1670a6fa6 to your computer and use it in GitHub Desktop.
Atlassian Bitbucket Server (Stash) OAuth1 example with Python

Based on this https://developer.atlassian.com/server/jira/platform/oauth/

generate private key

openssl genrsa -out jira_privatekey.pem 1024

generate public key

openssl req -newkey rsa:1024 -x509 -key jira_privatekey.pem -out jira_publickey.cer -days 365
openssl pkcs8 -topk8 -nocrypt -in jira_privatekey.pem -out jira_privatekey.pcks8
openssl x509 -pubkey -noout -in jira_publickey.cer  > jira_publickey.pem

Create Application Link with options generic and incoming

On the next screen Consumer Key is OauthKey, Consumer Name is shown to the Use on authorization and Public Key is from jira_publickey.pem file.

After that python client goes like this

Dependencies setup

python3 -m venv venv
source venv/bin/activate

pip install requests_oauthlib pyjwt cryptography

Client

#!/usr/bin/env python3
import json
import oauthlib
from requests_oauthlib import OAuth1Session

key = "OauthKey"
secret = open("oauth_privatekey.pem").read()

base_url = "https://bitbucket.example.com"
request_token_url = base_url+"/plugins/servlet/oauth/request-token"
access_token_url = base_url+"/plugins/servlet/oauth/access-token"
authorization_base_url = base_url+"/plugins/servlet/oauth/authorize"

access_token = {}
try:
    with open("access_token.json") as f:
        access_token = json.load(f)
    print("Access token loaded")
except Exception:
    pass

# Setup session
bitbucket = OAuth1Session(key,
        signature_method=oauthlib.oauth1.SIGNATURE_RSA, 
        rsa_key=secret,
        callback_uri='http://127.0.0.1/cb')

if not access_token:
    # Fetch a request token
    bitbucket.fetch_request_token(request_token_url)

    # Redirect user to Bitbucket for authorization
    authorization_url = bitbucket.authorization_url(authorization_base_url)
    print('Please go here and authorize,', authorization_url)

    # Get the authorization verifier code from the callback url
    redirect_response = input('Paste the full redirect URL here: ')
    bitbucket.parse_authorization_response(redirect_response)

    # Fetch the access token
    bitbucket.fetch_access_token(access_token_url)

    print("Access token saved to disk")
    with open("access_token.json", "w") as f:
        json.dump(bitbucket.token, f)
else:
    bitbucket.token = access_token

if bitbucket.authorized:
    print("Authorized")

    # Fetch a protected resource, i.e. user profile
    username = bitbucket.get(base_url+'/plugins/servlet/applinks/whoami').text
    print("Authenticated as user ",username)

    profile = bitbucket.get(base_url+'/rest/api/1.0/users/'+username)
    print(profile.json())

else:
    print("Not auhtorized!")

generate oauth rsa key with python

#!/usr/bin/env python3
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

private_key_file = "oauth_privatekey.pem"

try:
    with open(private_key_file, "rb") as f:
        private_key = serialization.load_pem_private_key(
                data=f.read(),
                password=None,
                backend=default_backend()
        )
    print("Using existing private key")
except FileNotFoundError as err:
    print("Generating new private key")
    private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
            backend=default_backend()
    )

    with open(private_key_file, "wb") as f:
        f.write(private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.PKCS8,
                encryption_algorithm=serialization.NoEncryption()
        ))
print("Public key is:")
print(private_key.public_key().public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
).decode())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment