Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
ChrisPaine
Active Contributor

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.

The next step

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.

The challenges

When it comes to the whole area of application management, there are some key problems to overcome.

  1. How to securely authenticate your mobile device.
  2. How to deliver any password /secret key to the device.
  3. How to disable the device's access to the system in the event that device is compromised/lost.
  4. Make all of that as easy and painless as possible.

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:

  • OAuth is cool, but just because you used something once doesn't mean it's right to do it again. One big problem in even attempting this was the lack of OAuth Provider libs
  • Mobile devices (well, many of them at least!) aren't particularly big (the whole point of being mobile. Things that you can do easily on a desktop, aren't so easy on device.
  • Entering passwords stinks.
  • Most/Many people have more than one mobile device now, phone, tablet, business phone,
  • Public/Private key schemes are cool, but don't solve the problem of distribution/identification.
  • Device management is overkill, and something that consumers will not accept.
  • Your employees are the consumers of your HR systems.
  • Why should employees accept what a consumer wouldn't?
  • If you are using HTTPS for all your communications then your comms are already pretty damn secure  - sending your password unencrypted (Basic Auth) isn't a problem.
  • By using "out of band" communications to transmit logon details, we increase the security.
  • By combining the login authentication with the application management views it is very transparent to the end user what is happening
  • Wish list: I'd use a QR Code to transmit the pairing and verification codes so user doesn't have to type them in.
  • Wish list: I'd use web sockets to immediately update the admin tables! But my refresh button isn't too bad...

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.

Device Management

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:

Quick aside about some awesome jQuery plug-ins

As a quick deviation from the main flow/topic (as was so poetically said by my friend and fellow SAP Mentor Prashanth):

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:

Anyway back on track now :smile:

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.

Checking Basic Auth in NWCloud

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!

Device management? No Sir! We'll just cancel your credit card.

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!)

In summary

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"!

Disclaimer, ramblings and what's next

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.



17 Comments
Labels in this area