Wednesday, September 30, 2015

UI Testing

This week I spent time looking at UI Testing using iOS 9 and XCode 7.

I'm not going to go through the details but I did find these two links to be good enough to get going.


The first one is a little light on the details but I found it useful in giving simple steps for adding UI testing to an existing app.

The second one, I thought, did a better job of showing how to actually assert test results once you got everything up and going.

So what was my intent with this and why should I take the time to add this to my current project(s)?

Well to be honest, it didn't take more than about 30 minutes to read the articles and get going.  I did do a test project prior to adding to my existing production, or to be production, apps.

For the conversion to Swift of Pain Logger I see this as an invaluable tool to verify that once I switch a view controller over it still works as it did before.

For my "in work" app I see adding this functionality now as a way of validating and protecting from regressions in the future.

In short, setting it all up, and running the first tests was fairly simple, and I think will be a valuable tool in the tool chest.

I spent most of my time diving into ReactJS this week.  There is a lot to learn here and I'm not convinced it is the right tool for the web app I am building.  Time will tell.  One thing I find hard is finding good training on the subject.  If anyone knows of good sources for this, particularly when using with Ruby on Rails, please pass them along.

There are a few articles, and I have probably read them all, but like most things, especially in the UI world, lots of folks have their opinion on how it should be done, with each one having different tradeoffs.  More investigation is needed.

Till next week.

Sunday, September 20, 2015

Security . . . Really?, Arggh!!

Prelude: This is a post I started writing a couple of weeks ago about my experience in adding authentication to a project I am working on.  It basically chronicles my thought process and how I explored and came to the decision of how I was going to implement this feature.  Whether it has much value to anyone other than my other team members I don’t know.  In the end I decided to post it mostly just to “complete the circle”.

Anyway, here goes:

Well, the Rails project I started a week ago has become a bit of a monster.  Basically it is a proof of concept right now.  The minimum goals are to allow a user to login to a web site or from a mobile device with either a registered account or through a service they are already a member of such as LinkedIn or Facebook.  

After last week’s effort, I had the test server up, so I decided the next step was to look at authentication since I had a feeling it might have impacts on the data model.  Also, since I needed to authenticate to other services (Facebook, LinkedIn, etc) I knew I would not be able to easily roll my own authentication scheme.  So I struck out looking for gem that could meet my needs.

It didn’t take long to run across the Devise gem as it seems to be used everywhere.

Vanilla Devise

I installed Devise into my application per the instructions on their site

It was fairly painless and worked great for authenticating the rails web site but this application also has the requirement to provide secure REST calls for mobile apps.  

That’s where things got complicated. One way to support this, and the one I zeroed in on, was to use token authentication.  The Devise gem used to have support for that baked in but in the latest versions it was removed.  

In the Devise documentation they explain why token authentication support was removed and provided links to two gems that would add it back in, devise_token_auth and simple_token_authentication.

Devise_Token_Auth

I first started with devise_token_auth as it looked to be much more robust and, quite frankly, when something has the word “simple” in it’s title like simple_token_authentication does, I read that as indicating while it may be simple it isn’t necessarily good for production.  

I spent several hours adding the devise_token_auth gem in.  The first hurdle was that it sits on top of Devise and as such when I originally installed Devise, the database migration wasn’t quite the same (at least out of the box) as the database migration for devise_token_auth. 

Since I am just learning the intricacies of Devise and token authentication I blindly followed the installation and configuration instructions for devise_token_auth. That was probably my first mistake, not surmountable, but a mistake none the less.

I was expecting it to create a migration to add to my existing user schema, but instead it created a new migration that created the same table as my original Devise authentication table, which obviously would fail if I ran “db:migrate".  Uh oh!

So to get back to a stable state I decided to remove the original Devise migration and use the one devise_token_auth generated instead.  This caused me to have to dump the database and recreate it.  I also had to manually change the order of the generated migrations so the user account would be created first.
 
This gave me one of those “what would happen in production if I had to change the authentication scheme” moments.  I decided that would not be a good day for me.  At this point in my exploration I was getting the feeling I was doing something wrong or didn’t understand something very fundamental.

It turns out devise_token_auth really is Devise with token authentication added back in. So, in hindsight I should have just started with the devise_token_auth gem, and not included and configured vanilla Devise beforehand. 

Once I corrected my mistake and got everything back up, reran the migrations and seeded the database I ran into an error in the devise_token_auth code itself.  It seems that the version of the devise_token_auth gem I had wasn’t compatible with the version of Devise I had originally installed.  Welcome to gem hell.

And, because the devise_token_auth gem is packaged as an engine, many of it’s inner workings were hidden from me.  To be honest I like the idea of packaging gems as engines, if they work, but this concept was foreign to me and made troubleshooting a bit harder when troubles arose. That didn’t feel good to me.

At this point I could have removed the Devise gem from my Gemspec and let the devise_token_auth gem install what it needed, but at the time I guess I was too dense to know that was the best course of action, so...

Simple_Token_Authentication 

To make progress I decided to switch to the other gem, simple_token_authentication.  As the name states it was simpler.  Another thing about it, that felt more comfortable to me, was it isn’t packaged as an engine so it was more what I was used to.  Finally it doesn’t replace Devise, instead it just enhances it a bit. Again, what I was expecting.

I followed the install instructions, added the before action, and created the migration as outlined on their site.  I was up and running again, the rails web site was now secured again and I had token authentication added in.  Next hurdle was a mobile client.

Mobile Integration

To do this I decided I would create a test iOS app that would first call the REST api on the rails app to sign-in, get the authentication token and then call a different REST method to get some data.  I figured if I could do this then I would have a basic setup that could be fleshed out further.

Unfortunately, I quickly ran into Apple’s ATS (App Transport Security) changes made in iOS 9.  These changes require the following of the server and client communication (from Apple’s site):


  • The server must support at least Transport Layer Security (TLS) protocol version 1.2.
  • Connection ciphers are limited to those that provide forward secrecy
  • Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key.
  • Invalid certificates result in a hard failure and no connection.


The implications of this was that I would need to switch my test server to use HTTPS.  Which I did by reconfiguring the web server (sitting in front of the rails app) and installing a self-signed certificate.

This created a different problem that I didn’t expect.  I could sign-in and get a valid authentication_token, but on the second REST call to get data I would get a string in my JSON saying "the certificate was not secure would I like to proceed anyway?"  

Apparently, a self-signed certificate isn’t good enough to pass the check list in ATS.  I googled around how to add exceptions to my app’s configuration.  There appear to be several ways to get around the problem.  I feel like I explored all of them but to no avail.

First, you can just allow all connections and disregard the invalid certificate problem by adding NSAllowsArbitraryLoads to your NSAppTransportSecurity section of your info.plist.  I did this first and my proof of concept app was up and running, albeit without any security checking.  

But, I know this isn’t the way to ship, and I figured if our project did go into beta production we would probably be using a self-signed certificate, so I dug deeper into the ATS configuration options.

According to their documentation, I should be able to set the NSExceptionAllowsInsecureHTTPLoads to by-pass the invalid certificate exception I was getting when making the second REST call.  I tried many different variations and tried a lot of other suggestions I found on Stack Overflow.  But I just couldn’t get it working, if anyone knows how (and has successfully done it) I would be very interested in what you did.

Conclusion

In short, this is a short synopsis of how painful adding token authentication has been.  Looking back at this post it doesn’t appear to be as bad as it was in reality.   I think one of the things that really tripped me up, and continues to this day, is all the terminology the security gurus use.  Just reading through the documentation on the various gems, they throw out a lot of new terms I was not familiar with so that probably added to my frustration.

So in the end, I think once we get closer to production and we have a legitimately signed certificate all of this will go away.  But for now, until I can figure out how to do it the right way, we’ll have to have our iOS app continue to “punch” through the security settings with the NSAllowsArbitraryLoads option.  Not ideal but expedient.

My final thoughts are that if I was doing this over again, and had more time to research and try things out, I would start with devise_token_auth as it feels much more robust and thought out but, at least at this point, I’ll go with the simple_token_authentication gem so I can make progress on the rest of the app.

Monday, September 7, 2015

When Plans Go Bad

I started my post out this week with the intent of looking at another charting package for iOS, JBChartView.  My intent was to deploy it in a playground much like I did for my iOS-Charts post.  

But after trying for several hours and “Googling” the world (it seemed like), the closest I could get was an invalid CGGraphicsContext exception when the view tried to render.  

I figure it had to do something with how drawing was being done in the package or I was missing some dependency that XCode was delightful enough not to tell me about!!

Anyway unless a ureka moment occurs or the new version of XCode (hopefully coming this week) solves this, I need to put this on the back burner so as to get some real work done.  Which is what I am going to briefly talk about instead.

After the frustration of the chart experienceI was looking for something a little easier to get my sanity back.  So I turned my attention to configuring a Ubuntu server for a Rails project I am starting on.  Everything was going great, dev environment was set up and running, git repository was stood up and was accepting pushes and life was good.  Then I turned to the test machine and I ran straight into the infamous “nokogiri" gem could not be installed issue.

Back to “Googling”, Arrrrgghhh!!!

Anyway a few hours later I found the fix.  So since it was so hard to find, I thought I would end my post this week with the answer in the hopes of making it more visible to the larger community.  So here goes:

If you are using RVM on Ubuntu 14.04 (Trusty) and the nokogiri gem is not installing when you attempt to install Rails, thus keeping you from installing Rails all together.  The error you see will say something about needing to install development tools.  

To fix this, you need to reinstall rvm WITHOUT the binaries so the header files that nokogiri needs can be found.  The command to reinstall RVM is:

rvm reinstall 2.2.3 --disable-binary

Hope this helps, see you next week.