pasé un día entero en la codificación de esta, después de varios intentos fallidos en las últimas semanas. Esto solo lo lleva al primer paso, pero lo hace sin ninguna biblioteca externa. Y sí, sé que es casi dos años después del OP, pero por lo que pude ver todavía tenía que hacerse.
#!/usr/bin/python
'demo Google OAuth'
import sys, os, urllib, urllib2, time, httplib
import hmac, hashlib, random, re, base64
PARAMETERS = {
'oauth_consumer_key': os.getenv('OAUTH_CONSUMER_KEY') or 'anonymous',
'oauth_signature_method': 'HMAC-SHA1',
'oauth_signature': '',
'oauth_timestamp': os.getenv('OAUTH_TIMESTAMP') or '%d' % time.time(),
'oauth_nonce': os.getenv('OAUTH_NONCE') or '%x' % random.getrandbits(64),
'oauth_version': '1.0',
'oauth_callback': os.getenv('OAUTH_CALLBACK') or 'callback',
}
SCOPE = {'scope': 'https://www.google.com/calendar/feeds/'}
SECRET = os.getenv('OAUTH_CONSUMER_SECRET') or 'anonymous'
def google_oauth():
'OAuthGetRequestToken, OAuthAuthorizeToken, OAuthGetAccessToken'
request_token = get_request_token()
return request_token
def get_request_token():
'ask Google for a request token'
url = 'https://www.google.com/accounts/OAuthGetRequestToken'
token_secret = '' # we don't have a token secret yet
PARAMETERS['oauth_signature'] = sign('&'.join((SECRET, token_secret)),
'&'.join(map(urlencode, ('GET', url, parameters('signing')))))
body = urllib.urlencode(SCOPE)
request = urllib2.Request(url + '?' + body)
request.add_header('Authorization', 'OAuth ' + parameters('header'))
opener = urllib2.build_opener(urllib2.HTTPSHandler(debuglevel = 1))
response = opener.open(request)
reply = response.read()
response.close()
return reply
def byte_encode(match):
'for use with re.sub'
return '%%%02X' % ord(match.group())
def urlencode(string):
"unreserved = ALPHA, DIGIT, '-', '.', '_', '~'"
return re.sub(re.compile('[^0-9A-Za-z._~-]'),
byte_encode, string.encode('utf8'))
def sign(secret, text):
print >>sys.stderr, 'signature base string: "%s", secret: %s' % (
repr(text), repr(secret))
digest = hmac.new(secret, text, hashlib.sha1).digest()
return urlencode(base64.encodestring(digest).rstrip())
def base64string(hexstring):
recoded = urlencode(base64.encodestring(hexstring.decode('hex')).rstrip())
print >>sys.stderr, 'recoded:', recoded
return recoded
def parameters(format):
if format == 'header':
formatted = ', '.join(['%s="%s"' % (key, value)
for key, value in PARAMETERS.items()])
elif format == 'signing':
formatted = '&'.join(sorted(['%s=%s' % (key,
urlencode(value.encode('utf8'))) for
key, value in (PARAMETERS.items() + SCOPE.items()) if
key not in ['oauth_signature']]))
#print >>sys.stderr, format, formatted
return formatted
def hmac_sha1_test():
'from tools.ietf.org/html/rfc2202'
assert sign('\x0b' * 20, 'Hi There') == base64string(
'b617318655057264e28bc0b6fb378c8ef146be00')
assert sign('Jefe', 'what do ya want for nothing?') == base64string(
'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79')
assert sign('\xaa' * 20, '\xdd' * 50) == base64string(
'125d7342b9ac11cd91a39af48aa17b4f63f175d3')
# last test from http://oauth.net/core/1.0/#rfc.section.9.1.1, app. A.5.2
assert sign('kd94hf93k423kf44&pfkkdhi9sl3r4s00',
'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26' + \
'oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3D' + \
'kllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26' + \
'oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26' + \
'oauth_version%3D1.0%26size%3Doriginal') == urlencode(
'tR3+Ty81lMeYAr/Fid0kMTYa/WM=')
return True
if __name__ == '__main__':
command = os.path.splitext(os.path.basename(sys.argv[0]))[0]
print eval(command)(*sys.argv[1:])
Guardar como google_oauth.py, y se puede enlazar con él de este modo:
ln -s google_oauth.py hmac_sha1_test.py
probar cualquiera de las subrutinas. En combinación con el uso de variables de entorno, puede comparar sus resultados con los de OAuth Playground de Google (otras personas aquí proporcionó el enlace) y ver dónde va mal. Encontré muchos problemas con el script de esa manera; puede haber muchos más. Pero si se invoca ./google_oauth.py, debería ver algo como esto:
[email protected]:~/rentacoder/marchie$ ./google_oauth.py
signature base string: "'GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dcallback%26oauth_consumer_key%3Danonymous%26oauth_nonce%3Da64720fda018906b%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1302253695%26oauth_version%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fcalendar%252Ffeeds%252F'", secret: 'anonymous&'
send: 'GET /accounts/OAuthGetRequestToken?scope=https%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2F HTTP/1.1\r\nAccept-Encoding: identity\r\nHost: www.google.com\r\nConnection: close\r\nAuthorization: OAuth oauth_nonce="a64720fda018906b", oauth_timestamp="1302253695", oauth_consumer_key="anonymous", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="LSJxopFXWN71sTSIBIkNeGgsOjc%3D", oauth_callback="callback"\r\nUser-Agent: Python-urllib/2.6\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: text/plain; charset=UTF-8
header: Date: Fri, 08 Apr 2011 09:08:20 GMT
header: Expires: Fri, 08 Apr 2011 09:08:20 GMT
header: Cache-Control: private, max-age=0
header: X-Content-Type-Options: nosniff
header: X-XSS-Protection: 1; mode=block
header: Content-Length: 118
header: Server: GSE
header: Connection: close
oauth_token=4%2FfvSIWW9WBHXa_CjInpOf4FdNYhCj&oauth_token_secret=qhB1EGIKjL1pG9POF2ZOcQk3&oauth_callback_confirmed=true
He estado trabajando en lo mismo durante todo el día, la esperanza de tener algo de trabajo pronto. –