Saturday, January 29, 2011

Mobile, Token Based Authentication

We've had some recent discussion on mobile authentication and thought it might be a good time to discuss how this works in the Where U At? application where we had white space to start fresh. For the most part we took a lot of insight from Twitter to use a token based authentication method, but not use OAuth. It's more of a service based OAuth that fits better in a paradigm where applications will interact as a service and want to tightly control the authentication service.

As everything in Where U At? it's a REST implementation that looks like the following (a few details are omitted):

  1. POST: /tokens
    1. Request Data
      1. email
      2. password
      3. manufacturerId
    2. Returns: Token
  2. GET: /tokens/{UUID}
    1. Returns: Token
  3. DELETE: /tokens/{UUID}
Behind the scenes we have a few objects that make this all work on the server.
  1. Token
    1. token_id
    2. expiration
    3. user_id
    4. device_id
  2. User
    1. user_id
    2. email
    3. name
    4. password (one way encrypted)
  3. Device
    1. device_id
    2. type
    3. manufacturer_id
    4. security_id
Any application can create a token (i.e. login) and store the token or token_id locally and reuse that. For any requests to our other services you simply pass an X-Token header with the token_id as the value. The other resources will validate the token is valid (i.e. that it exists and is not expired).

Any application can verify the token using a GET request if they so desire. Additionally, they can delete a token to perform a logout.

We follow a practice that only one user and one device can have a token active at any time. This means that if I login into my iPhone and then my iPad the token for the iPhone is deleted on the server. This works for us in a Location Based Application with push notifications to ensure only one device for a user is updating location at a time. It also ensures push notifications go to the right device.

A token_id has the same security behavior as a cookie based session id like every web app in existance these days and can be "stolen". To prevent this all requests are encrypted using standard SSL (not just login) so that only the server and device ever can see the token.

Where U At? Server Release 8 (1/29/2011)

Another month in the new year almost over and another release from team Where U At?! Another quick server release to upgrade to the new CityGrid v2 API's. With the new CityGrid v2 Offers API we are considering another upcoming release to make our deals/offers better!

Where U At? Server Release 8 (1/29/2011)
  1. CityGrid v2 API's which has made our app faster for finding places and locations!
What are you waiting for? Download the FREE app from http://bit.ly/whereuat

Monday, January 3, 2011

Where U At? Server Release 7 (1/3/2011)

Happy New Year from the Where U At? Team! We have a quick release in the new year to fix a few bugs.

Where U At? Server Release 7 (1/3/2011)

  1. Made the push notification text more clear when accepting a meetup
  2. Location access for a Friend was showing as Disabled even when you requested All The Time
Again, if you *still* haven't download our FREE app yet, you can download it from http://bit.ly/whereuat

Sunday, December 26, 2010

Disk Caching Protocol Buffers in iOS

There were a few times when we needed to persist Protocol Buffer objects retrieved from the Where U At? servers in order to reduce the frequency of GET calls per client (iPhone/iPad/iPod). You need to gauge your usage and determine when appropriate times are to cache, but for us, photos were an easy win.

If you haven't dabbled in Protocol Buffers for Objective-C, we highly recommend taking a look at http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers for starters.

By doing a bulk photos fetch (for every friend), and persisting to the local iOS documents cache directory, we can save an average of 5-8 calls per user per hour of usage. The following code demonstrates how to convert a Protocol Buffer object to an NSData stream for writing. We simply have these methods within a singleton Objective-C class:

#define USER_CACHE_ALL_PHOTOS_PATH @"All_Photos.pb"

- (NSString*) cacheDir {
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
if ([paths count] > 0) {
return [paths objectAtIndex:0];
}
return nil;
}

- (void)writePhotos {
if (photos != nil) {
NSOutputStream* rawOutput = [[NSOutputStream outputStreamToMemory] retain];
PBCodedOutputStream* output =
[[PBCodedOutputStream streamWithOutputStream:rawOutput] retain];
[photos writeToCodedOutputStream:output];
[output flush];
NSData* actualData = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
NSString* pathToStorePhotos =
[[NSString [self cacheDir], USER_CACHE_ALL_PHOTOS_PATH] retain];
[pathToStorePhotos release];
[output release];
[rawOutput release];
}
}

- (Photos*)readPhotos {
Photos* photosOnDisk = nil;
NSString* pathToStorePhotos = [[NSString
stringWithFormat:@"%@/%@",
[self cacheDir], USER_CACHE_ALL_PHOTOS_PATH] retain];
NSData *photoData = [[NSData dataWithContentsOfFile:pathToStorePhotos] retain];
if (photoData) {
photosOnDisk = [[[[Photos builder] mergeFromData:photoData] build] retain];
}
[photoData release];
[pathToStorePhotos release];
return [photosOnDisk autorelease];
}

Hope you enjoy this little snippet, it can be reused for all your objects that need long-term disk cache.

Where U At? Holiday Server Release 6

Happy Holidays from team Where U At? We've been slaving away with Santa's helpers to bring this great release. Ok, perhaps Santa's helpers had something different to do this past week and didn't actually help as much as we're saying. With much fanfare here's what we changed:

Where U At? Server Release 6 (12/26/2010)

  1. Set location "grey area" from 50% to 200% to prevent triggering too many "your friend is near" push notifications.
  2. Fixed reset password to work without giving a message that phone or email is required.
  3. Changed an invitation to simply send a Facebook post, email or SMS and to not automatically create a friendship as this was causing confusion.
  4. Actually send an SMS when inviting with a phone number... Imagine that!
  5. Proximity alerts now alert the owner of a meetup when an invitee arrives.
And just in case you haven't installed our app yet you can download it from http://bit.ly/whereuat

    Friday, December 24, 2010

    Objective-C Immutable Example

    With Objective-C there is no such thing as truly immutable example as you can always get at the memory and manipulate it (it's just pointers and memory after all). We had a goal of creating an immutable contract for Objective-C but still leverage the @property notation to minimize the memory management errors. The usecase is that in XCode any code type ahead would only show the read only accessors so that we know not to attempt to write to a property. But, internally in the class we can use the synthesized writeable accessors.

    Here's an example of how we did it. First, define an interface in a usual manner, but set the properties to @property (readonly). Specify an initializer that takes all the methods.
    #import <foundation/foundation.h>
    
    @interface FooItem : NSObject
    
    
    @property (nonatomic, retain, readonly) NSString* name;
    @property (nonatomic, retain, readonly) NSNumber* count;
    - (id) initWithValues:(NSString*) givenName withCount:(NSNumber*) givenCount; @end
    Then in the implementation define a no name category that specifies the actual properties to be synthesized. These are done as readwrite so that the implementation itself has write accessors. In the initializer still continue to use the self accessors to have the benefits of runtime memory management.
    #import "FooItem.h"
    
    @interface FooItem ()
    
    @property (nonatomic, retain, readwrite) NSString* name;
    @property (nonatomic, retain, readwrite) NSNumber* count;
    
    @end
    
    @implementation FooItem
    
    @synthesize name;
    @synthesize count;
    
    - (id) initWithValues:(NSString*) givenName withCount:(NSNumber*) givenCount {
        self = [super init];
        if (self) {
            self.name = givenName;
            self.count = givenCount;
        }
     
        return self;
    }
    
    - (void) dealloc {
        self.name = nil;
        self.count = nil;
     
        [super dealloc];
    }
    
    @end
    
    Note, you could go to a true immutable implementation which would do a copy of the objects given in the initializer and specify copy on the @property. That seems an unnecessary amount of overhead for everyday use.