TomorrowPlusX TomorrowPlusX - 5 months ago 19
iOS Question

NSData won't accept valid base64 encoded string

I'm implementing JSON Web Token authentication on the iOS (7) cient-side. It's working nicely. My app rceives tokens, and can make authenticated calls to my server with them.

Now, I want my client side code to check for an expiration date on the token so it can know when to re-authenticate. Checking for the expiration date on a JWT auth token is straightforward. The authorization token is 3 base64 encoded JSON blobs, separated by a '.' - The expiration timestamp is in the middle blob, in a field called

ext
. It's seconds since unix epoch.

So my code's looking like so:

- (NSDate*) expirationDate
{
if ( !_tokenAppearsValid ) return nil;

if ( !_parsedExpirationDate )
{
//
// Token is three base64 encoded payloads separated by '.'
// The payload we want is the middle one, which is a JSON dict, with
// 'exp' being the unix seconds timestamp of the expiration date
// Returning nil is appropriate if no 'exp' is findable
//

NSArray *components = [self.token componentsSeparatedByString:@"."];

NSString *payload = components[1];

NSData* payloadJsonData = [[NSData alloc]
initWithBase64EncodedString:payload
options:NSDataBase64DecodingIgnoreUnknownCharacters];

NSError* jsonError = nil;
NSDictionary* payloadJson = [NSJSONSerialization JSONObjectWithData:payloadJsonData options:0 error:&jsonError];
if ( payloadJson )
{
if ( payloadJson[@"exp"] )
{
NSTimeInterval timestampSeconds = [payloadJson[@"exp"] doubleValue];
_expirationDate = [NSDate dateWithTimeIntervalSince1970:timestampSeconds];
}
}

_parsedExpirationDate = YES;
}

return _expirationDate;
}


The problem is simple. The middle base64 blob, when parsed by NSData -initWithBase64EncodedString is
nil
- and that's bad.

I've checked the base64 blob and it seems to be valid. My server's returning dummy data for the moment so here's an example blob:
eyJlbWFpbCI6ImZvb0BiYXIuYmF6IiwiYWNjb3VudElkIjoiMTIzNDUtNjc4OTAtYmFyLWJheiIsImV4cCI6MTM5MDkxNTAzNywiaWF0IjoxMzkwOTE0MTM3fQ


It decodes to:

{"email":"foo@bar.baz","accountId":"12345-67890-bar-baz","exp":1390915037,"iat":1390914137}


I tested it here: http://www.base64decode.org

I've used NSData's base64 methods elswhere in my app with success - I don't think I'm doing anything particularly broken here. But I'm all ears! Any ideas?

Answer

Your Base64 string is not valid. It must be padded with = characters to have a length that is a multiple of 4. In your case: "eyJlbWFp....MTM3fQ==".

With this padding, initWithBase64EncodedString decodes the Base64 string correctly.

Comments