Trouble understanding API

103 views
Skip to first unread message

poedgirl

unread,
Oct 16, 2009, 12:33:18 PM10/16/09
to Google Apps Labs Short Links
I'm having real trouble understanding the API. Mainly the signature
part. I have made a PHP script based on the python script - however
it's only for generating a hashed URL. The code below, however, always
results in a 403 forbidden error when I try to execute the URL. The
signature below is what I understand the python code is doing, but I
just can't get it to work.

<?php

$server = "go.domain.com";
$secret = "secret";
$email = "te...@domain.com"

$urlToShort = urlencode($_GET['url']);

$baseurl = "http://".$server."/js/get_or_create_hash";
$parameters = "is_public=true&oath_signature_method=HMAC-
SHA1&shortcut=link&timestamp=".time()."&url=".
$urlToShort."&user=".urlencode($email);

$signature = urlencode(base64_encode(hash_hmac("sha1", "GET&".
$baseurl."&".$parameters, $secret, true)));

$url = $baseurl."?".$unescaped."&oath_signature=".$signature;

echo $url;

?>

Jens

unread,
Oct 19, 2009, 12:29:07 PM10/19/09
to Google Apps Labs Short Links
Hi,

The basic algorithm for building a signed url follows this process:
http://oauth.net/core/1.0a#signing_process
(without certain aspects, such as oauth timestamp/nonce or supporting
different signing mechanisms).

I created a simplified version of the python script and tried to put
your values in (see below; please compare that I am using the same
values for timestamp and your key/value pairs). The first thing I see
is that I believe you are not escaping your $parameters and $baseurl
when creating the signature. The signature base string in this example
should be like this:

GET&http%3A%2F%2Fgo.domain.com%2Fjs%2Fget_or_create_hash&is_public
%3Dtrue%26oauth_signature_method%3DHMAC-SHA1%26shortcut%3Dlink
%26timestamp%3D1255757382%26url%3Dhttp%253A%252F%252Fwww.google.com
%26user%3Dtest%2540domain.com

I believe your listing computes
hash_hmac("sha1", "GET&".$baseurl."&".$parameters, $secret, true)
which seems to suggest that the parameters and the base url are not
getting encoded.

Even after that, I'm still getting a different signature, but let's
take it one step at a time. Below are all the intermediate steps my
lisitng puts out. Can you take a look and tell me if I'm correct
regarding the escaping/unsecaping?

Base URL: http://go.domain.com/js/get_or_create_hash

unescaped parameters: is_public=true&oauth_signature_method=HMAC-
SHA1&shortcut=link&timestamp=1255757382&url=http%3A%2F
%2Fwww.google.com&user=test%40domain.com

Signature base string: GET&http%3A%2F%2Fgo.domain.com%2Fjs
%2Fget_or_create_hash&is_public%3Dtrue%26oauth_signature_method%3DHMAC-
SHA1%26shortcut%3Dlink%26timestamp%3D1255757382%26url%3Dhttp%253A%252F
%252Fwww.google.com%26user%3Dtest%2540domain.com

Signature: dbMuX9uZsj2cSnr9rPycPvy60Xs%3D

Final Request URL:
http://go.domain.com/js/get_or_create_hash?is_public=true&oauth_signature_method=HMAC-SHA1&shortcut=link&timestamp=1255757382&url=http%3A%2F%2Fwww.google.com&user=test%40domain.com&oauth_signature=dbMuX9uZsj2cSnr9rPycPvy60Xs%3D

Best regards,

Jens



#!/usr/bin/python2.4

import base64
import datetime
import hmac
import sha
import sys
import time
import urllib
import urllib2


def make_request_uri(hostname, api_method, secret, **parameters):
# What is the url (without parameters)?
base_url = 'http://%s/js/%s' % (hostname.lower(), api_method)

# What is the base query string?
parameters['oauth_signature_method'] = 'HMAC-SHA1'
parameters['timestamp'] = '1255757382'
param_array = [(k, v) for k, v in parameters.items()]
param_array.sort()
keyvals = ['%s=%s' % (urllib.quote(a, ''), urllib.quote(str(b), ''))
for a, b in param_array]
unescaped = '&'.join(keyvals)
print 'Base URL: %s' % base_url
print 'unescaped parameters: %s' % unescaped
signature_base_string = 'GET&%s&%s' % (
# base_url, unescaped) # This would be wrong; need to escape both
urllib.quote(base_url, ''), urllib.quote(unescaped, ''))
print 'Signature base string: %s' % signature_base_string

# Create oauth secret
signature = urllib.quote(base64.b64encode(
hmac.new(secret, signature_base_string, sha).digest()), '')
print 'Signature: %s' % signature

# Return the result
return '%s?%s&oauth_signature=%s' % (base_url, unescaped, signature)


def main():
request_url = make_request_uri(
'go.domain.com',
'get_or_create_hash',
'secret',
user='te...@domain.com',
url='http://www.google.com',
shortcut='link',
is_public='true')
print 'Final Request URL: %s' % request_url


if __name__ == '__main__':
main()
Message has been deleted

Jens

unread,
Oct 23, 2009, 6:36:18 PM10/23/09
to Google Apps Labs Short Links
very nice -- thanks for doing the port :-)

On Oct 22, 8:11 pm, Kathrin <kath...@vollick-tech.com> wrote:
> There were a few issues with your code, including the use of "oath_*"
> instead of "oauth_*" as parameters.
>
> I went ahead and took the liberty of doing a port of the Python code
> to PHP, and a function to parse the response and return the short
> URL.  Define your constants at the top.  You can also enable
> SHORTLINK_DEBUG if you want to watch how it works.
>
> <?php
> /**
>  * Google short links API demo
>  *
>  * @license    Public Domain
>  * @author     Kathrin <kath...@vollick-tech.com>
> */
> /*
>  * To the maximum extent permissible under law, the author of this
> code has waived all copyright
>  * and  related or neighboring rights to this short links demo, and
> hereby places it into the
>  * public domain. This work is published from the United States.
>  */
>
> define ('SHORTLINK_SERVER', '[your server]');
> define ('SHORTLINK_SECRET', '[your secret]');
> define ('SHORTLINK_EMAIL', '[your email]');
>
> define ('SHORTLINK_DEBUG', false);
> $url = 'http://www.vollick-tech.com';
>
> // If we're viewing this on the web, send it as plain text
> if (isset ($_SERVER['HTTP_HOST'])) {
>         header ('Content-Type: text/plain');
>
> }
>
> // Random keys
> // $key1 = substr (sha1 (uniqid (rand(), true)), 0, 8);
> // $key2 = substr (sha1 (uniqid (rand(), true)), 0, 8);
>
> echo "Testing short link generation:\n";
> // echo sprintf ("Public Hashed:    %s\n", short_link ($url, true,
> true));
> echo sprintf ("Private Hashed:   %s\n", short_link ($url, true,
> false));
> // echo sprintf ("Public Shortcut:  %s\n", short_link ($url, true,
> true, $key1));
> // echo sprintf ("Private Shortcut: %s\n", short_link ($url, true,
> false, $key2));
>
> function short_link ($url, $hashed = true, $public = false, $shortcut
> = '') {
>         // Base URL for the API call
>     $base_url = sprintf ('http://%s/js/%s', SHORTLINK_SERVER,
> $hashed ? 'get_or_create_hash': 'get_or_create_shortlink');
>
>     // API call parameters
>     $parameters = array (
>         'is_public' => $public ? 'true' : 'false',
>         'oauth_signature_method' => 'HMAC-SHA1',
>         'shortcut' => $shortcut,
>         'timestamp' => sprintf ('%0.1f', time()),
>         'url' => $url,
>         'user' => SHORTLINK_EMAIL,
>     );
>
>     // URL encode the parameters
>     $params_encoded = http_build_query ($parameters);
>
>     // Build the base URL for the signature
>     $signature_base = sprintf ('GET&%s&%s', urlencode ($base_url),
> urlencode ($params_encoded));
>     $signature = urlencode (base64_encode (hash_hmac ('sha1',
> $signature_base, SHORTLINK_SECRET, true)));
>
>     // Make the API call
>     $request_url = sprintf ('%s?%s&oauth_signature=%s', $base_url,
> $params_encoded, $signature);
>     $response = file_get_contents ($request_url);
>
>     if (defined ('SHORTLINK_DEBUG') && SHORTLINK_DEBUG) {
>         echo sprintf ("Signature base: %s\n", $signature_base);
>         echo sprintf ("Signature: %s\n", $signature);
>         echo sprintf ("Request URL: %s\n", $request_uri);
>     }
>
>     if (!$response) {
>         return false;
>     }
>
>     $decoded = json_decode ($response, true);
>
>     if (defined ('SHORTLINK_DEBUG') && SHORTLINK_DEBUG) {
>         echo "Response: \n";
>         var_dump ($decoded);
>     }
>
>     return sprintf ('http://%s/%s', SHORTLINK_SERVER, $decoded
> ['shortcut']);
>
> }
>
> On Oct 16, 12:33 pm, poedgirl <miche...@poedsoft.com> wrote:
>
> > I'm having real trouble understanding the API. Mainly the signature
> > part. I have made a PHP script based on the python script - however
> > it's only for generating a hashed URL. The code below, however, always
> > results in a 403 forbidden error when I try to execute the URL. The
> > signature below is what I understand the python code is doing, but I
> > just can't get it to work.
>
> > <?php
>
> >         $server = "go.domain.com";
> >         $secret = "secret";
> >         $email = "t...@domain.com"
Reply all
Reply to author
Forward
0 new messages