3 Implement BlueVia for Python - The oAuth Dance

This and the following chapter is about understanding the BlueVia low level API. To properly use it we need to understand two topics

Since the oAuth Dance also implies signing the request, let’s start with this one.

3.1 Creating correct and signed requests

To send a correct HTTP call to the BlueVia platform, we need to get 5 things in a correct way:

If one of them is not fully correct, your call will be rejected.

Let’s use the example of sending SMS:

1) As for any other API except the oAuth Dance, the request URL comes in two flavours:

https://api.bluevia.com/services/REST/SMS_Sandbox/outbound/requests
https://api.bluevia.com/services/REST/SMS/outbound/requests

The first URL is usually used to get the initial implementation right, calls will never touch the real mobile network and there will no costs be associated with these calls.

The second URL - without the “_Sandbox” string in the middle - will hit the real mobile network and you can use it during the development phase as long as you have free SMS credits available.

2) The query string here is simply the API version. Currently we have version 1

version=v1

3) Important here is an oAuth “Authorization” header plus a “Content-Type” header. This tutorial will be fully focussed on JSON, so the “Content-Type” normally will be “application/json” (exception: Advertising API)

"Authorization": 
    "OAuth realm=\"BlueVia\",
    oauth_body_hash=\"9E2QsTQeOy1N3ZkjH6jHgh7Sp5I%3D\",
    oauth_nonce=\"28892635\",
    oauth_timestamp=\"1311929069\",
    oauth_consumer_key=\"yT11072616762766\",
    oauth_signature_method=\"HMAC-SHA1\",
    oauth_version=\"1.0\",
    oauth_token=\"493c2c9316b2c75e2766c97477450b13\",
    oauth_signature=\"STcVSD80mvDfnDVrAikq1jckOhI%3D\"",

"Content-Type": "application/json;charset=UTF8"

The oauth_consumer_key is the key you’ve received during creation of the application on the BlueVia portal.
The oauth_token is the Access Token received after from the successful oAuth Dance.

4) Next look at the body. It contains the actual parameters for the SMS message.

{"smsText": {
    "address": { "phoneNumber": "447763654962" },
    "message": "Hello BlueVia", 
    "originAddress": { "alias": "493c2c9316b2c75e2766c97477450b13" }
  }
}

5) Finally we need to understand how the oAuth signature is created. The base string to apply the oAuth signature method on, is given below. We have to add all oauth header fields from above plus the version parameter and sort it in alphabetical order (Note: The line breaks have been added for readability reasons. In fact it is one long string):

POST&
https%3A%2F%2Fapi.bluevia.com%2Fservices%2FREST%2FSMS_Sandbox%2Foutbound%2Frequests&alt%3Djson%26
oauth_body_hash%3D9E2QsTQeOy1N3ZkjH6jHgh7Sp5I%253D%26
oauth_consumer_key%3DyT11072616762766%26
oauth_nonce%3D28892635%26
oauth_signature_method%3DHMAC-SHA1%26
oauth_timestamp%3D1311929069%26
oauth_token%3D493c2c9316b2c75e2766c97477450b13%26
oauth_version%3D1.0%26
version%3Dv1

And the key used to sign it is (the spaces around the “&” are again added for readability only):

key   = hofF15263457 & c3d65e3566aff260c8dbadc0437e2661

This key is a combination of the Consumer Secret (again received during app creation on the portal) and the Access Token Secret received during the oAuth Dance.

The values in 1) - 5) are exactly what we have to achieve in ordser to successfully send an SMS via BlueVia.

So, how is this to be done in python? The bluevia package contains a method _signAndSend(…). This routine is core to all calls and the the whole oAuth magic, so let’s analyze it:

def _signAndSend(self, requestUrl, method, token, parameters={}, body="", \
                 extraHeaders={}, is_form_encoded = False):

    req = oauth.Request.from_consumer_and_token(self.consumer, token,  \
                           method, requestUrl, parameters, body, is_form_encoded)       #(a)
    req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), self.consumer, token)           #(b)

    headers = req.to_header(realm=self.realm)                                           #(c)
    if parameters.has_key("xoauth_apiName"):                                            #(d)
        headers['Authorization'] += 
            ', xoauth_apiName="%s"' % parameters.get("xoauth_apiName")

    if extraHeaders:
        headers.update(extraHeaders)

    if is_form_encoded:
        params = [p for p in parameters.items() if p[0] in ["version","alt"]]           #(e)
    else:
        params = [p for p in parameters.items() if p and p[0][:6] != "oauth_"]              

    query = None                                                                        #(f)
    if params:
        query = "&".join(["%s=%s" % (p[0], p[1]) for p in params])
        if query:
            requestUrl += "?" + query

    response, content = self.http.request(requestUrl, method, body, headers)            #(g)
    return response, content

(a) First step is to create the oAuth Request object (oauth is the module name, since the bluevia package uses import oauth2 as oauth). It takes the following arguments:

requestUrl The URL for the specific API call
method The HTTP method that call uses “GET” or “POST”
token This token is the oAuth Access Token (except during the oAuth Dance)
parameters Parameters required by BlueVia to fulfill the call
body The body required by BlueVia to fulfill the call
extraHeaders Some calls require some extra HTTP headers to be applied
is_form_encoded flag whether the body is form encoded or not

We will go into detail later when we discuss each BlueVia API

(b) Create the oAuth signature for the request object req (basically step 5 from above). This signature will appear in the oAuth header as oauth_signature_

(c) Extract the the right headers from the request object req as HTTP headers and add the additional extraHeaders if exist

(d) The payment API uses RPC with an additional Authentication header entry (xoauth_apiName=“Payment”)

(e) Correct the parameters. For BlueVia we need to distinguish between

For an url encoded call only the first parameters appear in the query string.
For JSON or XML encoded calls all parameters not beginning with “oauth_” will be in the query string.

(f) Create the query string from the parameters and if exists, add the query string to the request URL.

(g) Finally make the call. For the sake of simplicity, this tutorial uses synchronous HTTP calls. To avoid UI blocking, this could be changed to asynchronous calls.

The following to paragraphs and chapter 4 will use the parameters of the _signAndSend() function to explain how each single API needs to be called.

3.2 Get a Request Token

Input for _signAndSend

requestUrl https://api.bluevia.com/services/REST/Oauth/getRequestToken
method POST
token None
parameters {“oauth_callback”:“oob”}
body ""
extraHeaders {}
is_form_encoded False

Output of _signAndSend

response["status"] = 200

content =
oauth_token=6b3b40c4432c4841ba17e48b0b342cfe&
oauth_token_secret=c8e931da1f90731dddf672a8e96f0201&
oauth_callback_confirmed=true

The HTTP status is 200 and content contains the Request Token and Secret (line breaks only for readability). The Request Token is used to form the authorization URL:

and the Request Token Secret is used to sign the next request to get the Access Token.

3.3 Get an Access Token

Since we are using out-of-band callback, the user authorization gives back a verifier, e.g. 648748. This will be used to exchange the Request Token with the actual Access Token.

Input for _signAndSend

requestUrl https://api.bluevia.com/services/REST/Oauth/getAccessToken
method POST
token Request Token and Secret with oAuth verifier added to it
parameters {}
body ""
extraHeaders {}
is_form_encoded False

Output of _signAndSend

response["status"] = 200

content =
    oauth_token=493c2c9316b2c75e2766c97477450b13&
    oauth_token_secret=c3d65e3566aff260c8dbadc0437e2661

The result is also called oauth_token and oauth_token_secret, but this time it holds the Access Token and Secret that needs to be stored securely by the application.