Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSData won't accept valid base64 encoded string

Tags:

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":"[email protected]","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?

like image 280
TomorrowPlusX Avatar asked Jan 28 '14 13:01

TomorrowPlusX


People also ask

What characters are not allowed in base64?

The base 64 digits in ascending order from zero are the uppercase characters 'A' to 'Z', lowercase characters 'a' to 'z', numerals '0' to '9', and the symbols '+' and '/'. % is not allowed in base64 encoding.

How do I verify base64 strings?

In base64 encoding, the character set is [A-Z, a-z, 0-9, and + /] . If the rest length is less than 4, the string is padded with '=' characters. ^([A-Za-z0-9+/]{4})* means the string starts with 0 or more base64 groups.

How do I decrypt a base64 string?

To decode with base64 you need to use the --decode flag. With encoded string, you can pipe an echo command into base64 as you did to encode it. Using the example encoding shown above, let's decode it back into its original form. Provided your encoding was not corrupted the output should be your original string.


2 Answers

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.

like image 117
Martin R Avatar answered Oct 11 '22 17:10

Martin R


Although Martin's answer is correct, here is a quick and correct(!) way to fix the problem:

NSString *base64String = @"<the token>"; NSUInteger paddedLength = base64String.length + (4 - (base64String.length % 4)); NSString* correctBase64String = [base64String stringByPaddingToLength:paddedLength withString:@"=" startingAtIndex:0]; 
like image 35
christopher Avatar answered Oct 11 '22 16:10

christopher