Wednesday 25 September 2013

HTTP Basic authentication with Rails for iOS

Recently I've been getting into iOS and developing a interesting iOS app (more info coming soon!)

But, as the app is all about showing data of course I needed to create an API in my rails app to feed that data. But, I didn't want someone else to be able to grab it.

The Rails App Side

Configure a custom MIME type

First thing I did was set up a custom mime type in initializers/mime_types.rb:
Mime::Type.register_alias "text/json", :theapp
That let me call urls like /give_me_data.theapp

Add the 'respond_to'

In the applicable controllers add a respond_to (well, I already had one, so add to it):
respond_to :html, :xml, :theapp

Make templates with json_builder

I luuuvvvvv the json_builder gem. So I created a whack of templates with the .json_builder extension. Because of the mime type setting it would automatically get called.

Add the http_authentication stuff

I am a little bit lazy, so, I just chuck this into my application_controller. That means that all :theapp requests need authentication:

protected
def http_basic_authentication
    if request.format == :ios
        authenticate_or_request_with_http_basic do |username, password|
            username == 'myAmazingApp' && password == 'theBestestPasswordEver'
        end
    end
end

The iOS app side

The URLs

Simply chuck your authentication stuff into your urls:
NSString *const RegionDataBaseURL = @"http://myAmazingApp:theBestestPasswordEver@localhost:3000/regions/%@.theapp";

Pulling...Data

I do my stuff like this (thanks to Ray Wenderlich):
  dispatch_async(kBgQueue, ^{
    NSURL *url = [NSURL URLWithString: [NSString stringWithFormat:RegionDataBaseURL, [self.region permalink]]];
    
    NSData* data = [NSData dataWithContentsOfURL: url];
    [self performSelectorOnMainThread:@selector(fetchedRegionData:)
                           withObject:data waitUntilDone:YES];
  });
Yes, I could also put the username and password in some other place and sub it into the URL, but brute force works for now.

Like I say, I am starting out in iOS so maybe this is too noddy for all you pros, but, it works.

No comments: