Hello, back again with another blog in my and joanna.chans series on building a Cloud based mobile application.
Last time I wrote about the fun I was having authenticating users to the SAP NetWeaver Cloud application without using the standard built in SAM.... Instead of the standard SAML, we were aiming to have a more consumer focused logon using Twitter, Facebook and Google. Well once that started to work, we were up to the next exciting phase of our adventure.
Somewhat unsurprisingly (if you know me) at the beginning of our build, Jo and I sketched out what is was we were going to do, and how we'd break that down into tasks.
It seems that in our Mobile App that uses the cloud - the cloud is clearly at the centre of everything! This is again somewhat unsurprising - adopting the use of the "cloud" is going to be a big advantage to businesses that make that step forward.
We needed to build a set of RESTful APIs (I'll write about the challenges of that in another blog) in the cloud that the mobile device could use to get data from and send data to. But in order for those API calls to work, we needed somehow to authenticate our device with the cloud.
When it comes to the whole area of application management, there are some key problems to overcome.
I thought about this a fair bit (and to be honest am still thinking about it.) The video below talks through some of my thoughts.
Please note that SCN sizes the videos a fair bit smaller than they can be viewed - this vid for example was rendered and uploaded to YouTube at 640x480 (anamorphic) res so could happily be viewed at 860x480 res, but you'll have to open it in another browser to see that! - user this link - http://www.youtube.com/embed/_HuyN_pyb6U
In a nutshell:
In the end we built something which is pretty similar (in functionality) to the SuccessFactors application authentication (video linked) - but I think looks nicer :smile: I also think that by going from cloud to device rather than device to cloud, we have future options around things like using QR Codes which would be hard the other way around.
On successful sign in to the application (web page) using OAuth you can go to the device management page:
Here you can add a new device by pressing on the nicely styled (using JQueryUI ThemeRoller) add device button:
As a quick deviation from the main flow/topic (as was so poetically said by my friend and fellow SAP Mentor Prashanth):
Prashanth
@sprabuMy thoughts don't flow like a stream. They grow like a tree with thick and thin branches. How am I supposed to fit them in a PowerPoint
— Prashanth (@sprabu) January 9, 2013
I've seen where SAPUI5 is going, and it impresses the hell out of me that such a team is putting together some really great stuff. But I'm even more impressed (sorry SAPUI5 team) with what is generally available out there anyway. For example, I was able to theme the buttons and the table that I'm using without having to do any serious CSS manipulation myself. I just used ThemeRoller to build a theme that matched my company's colours and then it was automagically picked up by the jQuery plug-in table API I used (DataTables). And obviously the jQueryUI buttons I used picked up the theme. But the next bit I managed to find, was the icing on the cake... Clicking on the name of the device enables me to edit in-place and rename it. Pressing enter saves the update.
Pretty awesome really! and pretty simple too - use the Jeditable plug-in for jQuery and then a few lines of code:
$('#deviceTable').dataTable().$('td.editable').editable(updateDeviceName, {
"indicator" : 'updating...',
"tooltip" : 'Click to edit...',
"callback" : function(sValue, y) {
var deviceTable = $('#deviceTable').dataTable();
var aPos = deviceTable.fnGetPosition(this);
deviceTable.fnUpdate(sValue, aPos[0], aPos[1]);
},
"submitdata" : function(value, settings) {
return {
"row_id" : this.parentNode.getAttribute('Id'),
"column" : $('#deviceTable').dataTable().fnGetPosition(this)[2]
};
},
"height" : "14px",
"width" : "100%"
});
The above sets the table element (previously given class of "editable") to call the below function on pressing enter.
function updateDeviceName(value, settings) {
var deviceTable = $('#deviceTable').dataTable();
var deviceURL = deviceTable.fnGetData(this.parentNode, 5);
var blocked = deviceTable.fnGetData(this.parentNode, 3);
var devices = {
"Devices" : {
"DeviceName" : value,
"Blocked" : blocked,
}
};
var devicesJson = JSON.stringify(devices);
$.ajax({
type : "PUT",
url : deviceURL,
data : devicesJson,
dataType : "json",
async : false
}).fail(postErrorThrown);
return (value);
}
A very simple function which takes values from current table line and then PUTs this update back into the resource that is the device. Much more intuitive than having to select a table line so that it can be edited in some fields and pressing a submit button... :wink:
So once you've added your device on the web page, you can enter the pairing code into the mobile application.
Once you've done that, the mobile app makes a call to a resource keyed by the pairing id. That API returns details about the device, including the user id it is associated with and the username and password that should be used for all subsequent communications from the device.
{
"Devices": {
"Id": 1,
"URL": "http://chris.wombling.com:8080/DiscoveryTimesheetDemo/TimeSheetDevice/1",
"AssociatedUser": "http://chris.wombling.com:8080/DiscoveryTimesheetDemo/TimeSheetUsers/1",
"AssociatedUserId": 1,
"DeviceName": "Chris Paine device",
"PairingKey": null,
"ValidationKey": "179937",
"PairedDate": "16/01/2013",
"Secret": "cd81620a-349a-4745-9849-3eb2e4b84da6",
"Blocked": "N"
}
}
At this point the device looses it's pairing key - it is now paired. Any subsequent requests will return a 404 from the server. All further communication to the Cloud needs to be authenticated using the username ("AssociatedUserId") and the password ("Secret"). In trying to keep in the spirit of RESTful services - all the other resources in my app are then discoverable from the one "AssociatedUser" URL.
Each REST API that I have in my Cloud application calls some common authentication code to check that the user is valid. Firstly I check if there is a cookie to authorise the user (used by web interface). If the cookie doesn't exist or validate, I then check for basic authentication. Here's the code snippit which does the Basic Auth:
if (user == null) {
// check if the authentication is instead being handled by basic
// auth...
String authHeader = request.getHeader("Authorization");
if (authHeader != null) {
logger.debug("auth string found in header " + authHeader);
// attempt to parse out the user id and password
String base64 = authHeader
.substring(authHeader.indexOf(" ") + 1);
if (base64 != null) {
String decodedValue = Base64.base64Decode(base64);
logger.debug("decoded value " + decodedValue);
// split at ":"
String username = decodedValue.substring(0,
decodedValue.indexOf(":"));
String password = decodedValue.substring(decodedValue
.indexOf(":") + 1);
if (username != null && password != null) {
logger.debug("decoded values username" + username
+ " password " + password);
int id = Integer.parseInt(username);
TimeSheetMobileApp device = userData
.getDeviceFromId(id);
if (device != null) {
if (device.getBlocked().equals("N")) {
if (device.getSecret().equals(password)) {
user = device.getAssociatedUser();
}
}
}
}
}
}
}
return user;
I realise there are issues with the code that will most likely cause it to crash if it's supplied with anything other than what I expect it to be. But a few try/catch blocks should fix that (and make it much harder to read for the purposes of this blog...) (I'd also like to enhance the method to throw exceptions rather than just returning a null if the user isn't authorised. <sigh> so much #TODO) But, my aim here isn't perfection, but to show you what can be achieved!
If you're particularly into your code, you might have noticed that the above authentication routine checks to see if the device is marked as "blocked". On the same page where we added the device and found the pairing code, we have the option to lock each device. This stops the devices from being able to use their username and password that was assigned during pairing. The typical use case is where the user thinks that they might have lost their phone but isn't sure.
It's like putting your credit card over limit, rather than cancelling it. Because, as someone who's had their credit card cancelled due to a bank error, I can tell you it's a great big pain having to go and change the numbers in all the places you use it. Having also been over limit a few times, it's nice to know that it's temporary and can be fixed, nevertheless it sure stops things working! That's what our device management table allows - a simple way for users to stop the application working on a device and then re-enable it if needed. But they can also completely remove a device if required.
Of course, administrators can also do this on behalf of existing users (although I haven't built the front end for that functionality yet!)
What we've put together is a very simple way that anyone could copy and use (and please do!) to authenticate and manage a very simple mobile application that uses SAP NWCloud.
What this isn't is a way to manage devices and/or deploy and manage applications centrally. But instead a very simple and relatively secure solution for ensuring that those consumer type users can start benefiting from mobile apps.
I'm sure I'm touching on a few raw nerves here by not espousing SAP's mobile device management technology in this area (especially after their new and better application management announcements late last year), but I think there is a place for these simple more consumer focused solutions, especially where the data concerned isn't a worry if it's exposed. That, and this is "FREE"!
Again, I'd like to thank my wonderful employer for giving me the time to play with this tech, and to absolve them for the blame. These ramblings, thoughts, code errors, etc. are my own and in no way should be taken to be representative of my employer, unless they want it to. (And I didn't stop to ask which bits they thought were representative, probably because I was up until 1:45am writing blogs like this.) I do write these blogs in the hope that someone will find them useful, so if you do (or don't), please leave a comment, I'd love to know what you think. :smile:
Stay tuned for the next in the series, where Jo is going to do a tell-all exposé on the joys of mobile development and why she might be starting to like Android a bit more :grin: (or not, we'll wait and see). I will also be writing about the fun I've had building RESTful APIs using JSON (not a speck of OData) in the cloud with SAP NWCloud and my thoughts (and painful learnings) about that.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
37 | |
10 | |
6 | |
4 | |
3 | |
3 | |
3 | |
3 | |
2 | |
2 |