- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
If you are new to oAuth, Please read these links first : http://oauth.net/2/ and http://en.wikipedia.org/wiki/OAuth. Go ahead, I'll wait.
Why are we talking about oAuth today? Most of the services these days, are moving away from Basic Authentication for various reasons into oAuth. Twitter, Citrix Goto Meeting etc..
Service Now doesn't exactly "support" oAuth. But Service Now is so extensible with HTTP Client, that you can mimic oAuth and its 3 - legged dance.
For demonstrating this, I will do an oAuth authentication with Twitter. To make it more readable, I will do this in two posts. I chose twitter 'coz most of us use it, and there is a lot of help around.
Twitter oAuth flow is described in detail here : https://dev.twitter.com/docs/auth/implementing-sign-twitter
It involves 3 steps:
1. Obtaining a request token - You will use this token to re-direct your user to a page where he can gives access to your application. You must have seen this page often, where when you try to sign in using twitter, you will be redirected to a page which asks you if you grant permission.
2. Once the user grants permission, collecting the token - Which says - the user Approved your application.
3. Now this is the final step - In this step, we convert the token into a access token( remember the work "access" ) we, store this access token and we use it to make calls to Twitter API, on behalf of user.
That in a nutshell is 3-legged dance.
We will not do anything fancy like the 3-legged dance today, but we will talk about the basic blocks of any oAuth authorization. i.e., We will start our communication from the Step 3 above. Twitter will allow the Author of the application to make calls to his own account. i.e., If I've created a Twitter app, and I want to only pull the data from my Twitter Account, I can simply skip the first two steps. Twitter gives me an Access Token when I create my app, which I can use to directly make calls to API. I know you must be wondering how this is oAuth. Its not, What we see today is the signing process and Percentage encoding process.
We will be doing two things today:
1) Creating a new Twitter Application
2) Getting the tweets on your time line.
Creating a new Twitter Application: We need to create a Twitter App, so that any requests that go from Service Now to Twitter will be made from this application. Creating this Application is simple - Go to developers page here : https://dev.twitter.com/apps and create an app. You should note down 4 important things for today:
1. Consumer Key of your application
2. Consumer Secret of your application
3. Access token
4. Access token Secret
Getting tweets
Before going through the script, Please take some time to understand how Sign In is implemented in Twitter from here : https://dev.twitter.com/docs/auth/implementing-sign-twitter
https://dev.twitter.com/docs/auth/creating-signature
https://dev.twitter.com/docs/auth/authorizing-request
Now, here's the Script to get the tweets from your timeline- Comments inline.
var TwitterHelper = Class.create();
TwitterHelper.prototype = {
initialize: function() {
this.user = 'abhididdigi';
// This should be the same callback which we specified while creating the app.
this.callBack = 'http://www.servicenowdiary.com';
// Consumer key of your Twitter Application
this.consumerKey = 'M3HO0VL55555555UnTA'; //dummy
// This is the random alphanumeric string that needs to be generated. Twitter needs this
// to keep track of your requests
this.nounce = this.getNonce();
// This is the Algorithm that needs to be used to sign your requests to twitter.
this.signature_method = "HMAC-SHA1";
// The time stamp is the amount of time in seconds since UNIX epoch
this.timeStamp = this.getTimeStamp();
//Version of oAuth to be used.
this.version = "1.0";
this.encodedString = '';
//Any other parameters that you want to set when you initialize this Script Include.
this.method = 'POST';
this.baseURL = "https://api.twitter.com/oauth/request_token";
},
getNonce:function(){
// using generateGUID you can generate a sys_id, which is a random 32 <strike>bit </strike> character string.
// We will use this to set nounce.
return gs.generateGUID('');
},
// Simple - Using Packages.java.lang you get your time in seconds.
//Note - Packages.java.<> are still supported. Thank God!
getTimeStamp:function(){
var a =Packages.java.lang.System.currentTimeMillis() / 1000;
a = a.toString();
a= a.split('.')[0];
a = a*1;
gs.log("TimeStamp" + a);
return a;
},
// Now this is the important part. Creating a Signature.You have to collect
// all the parameters that you are sending and then, sign them. So that twitter
// can confirm that its you sending the request, and not somebody else.
//This function takes 3 parameters.
createGenericSignature:function(params,URL,method){
var ts = this.timeStamp+ '';
var o = {};
// We percent encode all the parameters, and then get them in the format
// that twitter accepts.
o[this.percentEncode('oauth_consumer_key')] = this.percentEncode(this.consumerKey);
o[this.percentEncode('oauth_nonce')] = this.percentEncode(this.nounce);
o[this.percentEncode('oauth_signature_method')] = this.percentEncode(this.signature_method);
o[this.percentEncode('oauth_timestamp')] = this.percentEncode(ts);
o[this.percentEncode('oauth_version')] = this.percentEncode(this.version);
for(var i in params){
o[this.percentEncode(i)] = this.percentEncode(params<i>);
}
var paramString = this.percentEncode(o);
var baseString = method+"&"+this.percentEncode(URL)+"&"+this.percentEncode(paramString);
var MAC_ALG = "HmacSHA1";
/* ! Important !*/
// Here the key is generate using Consumer secret and the Access token Secret that you
// collected above. So the format is <b>consumer_secret&access_token_secret</b>
key = this.percentEncode('DNiwawdawdawddddddddddddddHgMe61DYhZw1pI')+'&'+'cyVKrbpFQ8cw5iTSawdDTGuwdawdawdawdzpOtxWi5sz09Ig'; //dummies
// We sign it using HMACSHA1
var signat = Packages.com.snc.authentication.digest.Authentication.encode(baseString,key, MAC_ALG);
// Here comes the subtlety of Javascript, signat stores a Java.lang.String object!
// Hence typecasting it into a Javascript string.
signat = signat+'';
return signat;
},
//This function makes all the POST and GET calls.
//Today we look at GET because we are getting our time line.
makeCall:function(params,signature,method,URL,body){
//Get HTTP Client instance.
var client = new Packages.org.apache.commons.httpclient.HttpClient();
var arr = [];
//Prepare as per the format needed.
var prep = {};
prep[this.percentEncode('oauth_consumer_key')] = '"' + this.percentEncode(this.consumerKey) +'"';
prep[this.percentEncode('oauth_nonce')] = '"' + this.percentEncode(this.nounce) +'"';
prep[this.percentEncode('oauth_signature')] = '"' + this.percentEncode(signature) +'"';
prep[this.percentEncode('oauth_signature_method')] = '"' + this.percentEncode(this.signature_method) +'"';
prep[this.percentEncode('oauth_timestamp')] = '"' + this.percentEncode((this.timeStamp+'')) +'"';
prep[this.percentEncode('oauth_version')] = '"' + this.percentEncode(this.version) +'"';
for(var i in params){
prep[this.percentEncode(i)] = '"' + this.percentEncode(params<i>+'') +'"';
}
for(var i in prep){
if (prep.hasOwnProperty(i)) {
arr.push(i+"="+prep<i>);
}
}
arr.sort();
var strA = ', ';
var finalStr = arr.join(strA);
finalStr = "OAuth "+ finalStr;
gs.log(finalStr);
if(method == 'GET'){
var get =
new Packages.org.apache.commons.httpclient.methods.GetMethod(URL);
//Set the request header.
get.setRequestHeader("Authorization",finalStr);
get.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var status = client.executeMethod(get);
gs.log(status);
//Execute.
gs.log("Response"+ get.getResponseBodyAsString());
var json = new JSON();
var obj = json.decode(get.getResponseBodyAsString());
//Logging your time line.You have the JSON object now. Send it to client side, Display it/Store it.
JSUtil.logObject(obj);
get.releaseConnection();
}
},
// Place where it all starts...
own:function(){
var ts = this.timeStamp+ '';
var o = {};
/*! Important !*/
// Here is the Access Token that you collected above.
o['include_entities'] = 'true';
o['oauth_token'] = '58825564-l9gngrh4nAswUawdawdawdawdawdbZAFZuaQffD3GOjFg'; //dummy
var signat = this.createGenericSignature(o,'https://api.twitter.com/1.1/statuses/home_timeline.json','GET')
var s = {};
/*! Important !*/
// Here is the Access Token that you collected above.
s['oauth_token'] = '58825564-l9gngrh4nAsxdfsdfsdfsdfsdfA5bZAFZuaQffD3GOjFg';//dummy
this.makeCall(s,signat,'GET','https://api.twitter.com/1.1/statuses/home_timeline.json?include_entities=true','');
},
//Utility functions.
// Percentage Encode function - Encodes the given parameters in UTF-8.
percentEncode:function(params){
if(typeof params =='string'){
var ENCODING = "UTF-8";
var s = params;
s= s.toString();
//URLEncoder still works!
// Replacing characters like +,* as they need to be encoded differently as per oAuth
var a = Packages.java.net.URLEncoder.encode(s, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
var a = a+'';
return a;
}
if(typeof params == 'object'){
var arr = [];
for(var i in params){
if (params.hasOwnProperty(i)) {
arr.push(this.percentEncode(i)+"="+this.percentEncode(params<i>));
}
}
arr.sort();
return arr.join('&');
}
},
type: 'TwitterHelper'
};
Usage:
new TwitterHelper().own();
We will dance in the next post!
Note 1: More information on Percentage Encode : http://servicenowdiary.com/2013/06/a-server-side-function-to-percent-encode/
Note 2: Folks on Calgary, I'm sorry. I don't know how to replace HTTPClient Package call.
Raised a forum topic too, Keep an eye on it if you are interested.
Its not mentioned here too : http://wiki.servicenow.com/index.php?title=Packages_Call_Replacement_Script_Objects , But you will find replacements for all other Package calls used in this post in the above link.
- 1,577 Views
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.