Skip to content

Instantly share code, notes, and snippets.

@st4lk
Created May 15, 2015 20:45
Show Gist options
  • Save st4lk/719729c03cf0314179b4 to your computer and use it in GitHub Desktop.
Save st4lk/719729c03cf0314179b4 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
"""
Example of less-legged client workflow using OAuth means.
OAuth 1.0a is a 3-legged process. Less-legged process is not an OAuth 1.0a,
it just use similiar means, but people used to call it OAuth...
With 2-legged process user is not interacted in process.
In such workflow client application is acting like a user.
So client can fetch resources avaliable either to all users, either it can
access to resources owned by itself (even private).
API of bitbucket is used: https://confluence.atlassian.com/display/BITBUCKET/OAuth+on+Bitbucketß
"""
import random
import time
from urllib import quote, urlencode
import urllib2
import binascii
import hashlib
import hmac
# Constants given by service provider
CONSUMER_KEY = 'your_app_key'
CONSUMER_SECRET = 'your_app_secret'
REQUEST_TOKEN_URL = 'https://bitbucket.org/api/1.0/oauth/request_token'
AUTHORIZE_URL = 'https://bitbucket.org/api/1.0/oauth/authenticate'
ACCESS_TOKEN_URL = 'https://bitbucket.org/api/1.0/oauth/access_token'
# Values that choose client application
CALL_BACK = 'http://127.0.0.1/oauth1_callback'
API_RESOURCE_URL = 'https://api.bitbucket.org/1.0/repositories/{user}/{repo}/'.format(
user='lexev', repo='tutorial')
# Helpful functions
q = lambda x: quote(x, safe="~")
get_timestamp = lambda: int(time.time())
get_nonce = lambda: str(str(random.getrandbits(64)) + str(get_timestamp()))
def get_sign(params, url, http_method, oauth_token_secret=""):
"""returns HMAC-SHA1 sign"""
params.sort()
normalized_params = urlencode(params)
base_string = "&".join((http_method, q(url), q(normalized_params)))
sig = hmac.new("&".join([CONSUMER_SECRET, oauth_token_secret]), base_string, hashlib.sha1)
return binascii.b2a_base64(sig.digest())[:-1]
# Start oauth 1.0 2-legged process
# Or maybe it is called 0-legged process, or 1-legged...
# oauth 1.0a standard explains only 3-legged process, less-legged process
# is not an oauth 1.0a in fact.
####################################
# STEP 1: request to server resource
####################################
# Note, no auth token is present
params_confirmed_access_token = [
('oauth_consumer_key', CONSUMER_KEY),
('oauth_nonce', get_nonce()),
('oauth_signature_method', "HMAC-SHA1"),
('oauth_timestamp', get_timestamp()),
('oauth_version', '1.0'),
]
# signature
signature = get_sign(params_confirmed_access_token, API_RESOURCE_URL, "GET")
params_confirmed_access_token.append(('oauth_signature', signature))
# GET https://api.bitbucket.org/1.0/repositories/lexev/tutorial/?
# oauth_consumer_key=your_app_key&
# oauth_nonce=165399630806490086601427390977&
# oauth_signature_method=HMAC-SHA1&
# oauth_timestamp=1427390977&
# oauth_version=1.0&
# oauth_signature=aK%2BkRS5B%2BoFzXjMcQ%2FBtTMMELYk%3D
url = "?".join((API_RESOURCE_URL, urlencode(params_confirmed_access_token)))
resp = urllib2.urlopen(url)
assert resp.code == 200
print resp.read()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment