Have to use Quickblox's RESTful API instead of their iOS SDK due to work restrictions, and having trouble generating a valid signature according to their tutorial.
Below is the response I get from my call:
2014-07-25 16:19:12.646 test[2247:60b]response: <NSHTTPURLResponse: 0x10c41ae40> { URL:https://api.quickblox.com/session.json } { status code: 422, headers {
"Access-Control-Allow-Origin" = "*";
"Cache-Control" = "no-cache";
Connection = "keep-alive";
"Content-Type" = "application/json; charset=utf-8";
Date = "Fri, 25 Jul 2014 23:19:12 GMT";
"QuickBlox-REST-API-Version" = "0.1.1";
Server = "nginx/1.0.15";
Status = "422 Unprocessable Entity";
"Transfer-Encoding" = Identity;
"X-Rack-Cache" = "invalidate, pass";
"X-Request-Id" = 8413fb7182cee06857619b14f363ed78;
"X-Runtime" = "0.004821";
"X-UA-Compatible" = "IE=Edge,chrome=1";
} } data: {"errors":{"base":["Unexpected signature"]}} connectionError: (null)
And below is the method I'm using make the call:
- (void) retrieveQBTokenTest{
// Authentication data
NSString *appId = @"12345";
NSString *authKey = @"ypqdqEx7sOeWEQr";
NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
NSString *nonce = [NSString stringWithFormat:@"%i", (arc4random()%1000)+1];
NSString *authSecret = @"dtoA5bkNrBUZn5L";
NSString *dataStringForSig = [NSString stringWithFormat:@"application_id=%@&auth_key=%@&nonce=%@×tamp=%@", appId, authKey, nonce, timestamp];
NSString *sig = [self hmacsha1:dataStringForSig secret:authSecret];
// Package authentication data into JSON
NSDictionary *dict = @{
@"application_id":appId,
@"auth_key":authKey,
@"timestamp":timestamp,
@"nonce":nonce,
@"signature":sig
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
options:0
error:&error];
NSLog(@"%s: jsonString: %@", __FUNCTION__, [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding]);
// Generate request
NSURL *url = [NSURL URLWithString:@"https://api.quickblox.com/session.json"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
// Headers
[request setHTTPMethod:@"POST"];
[request setValue:@"0.1.1" forHTTPHeaderField:@"QuickBlox-REST-API-Version"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
NSString *length = [NSString stringWithFormat:@"%lu", (unsigned long)[jsonData length]];
[request setValue:length forHTTPHeaderField:@"Content-Length"];
// Body
[request setHTTPBody:jsonData];
// Make call
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *dataResponseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%s: response: %@ data: %@ connectionError: %@", __FUNCTION__, response, dataResponseString, connectionError);
}];
}
And finally, my hashing method:
- (NSString *)hmacsha1:(NSString *)data secret:(NSString *)key {
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *hash = [HMAC base64EncodedStringWithOptions:0];
return hash;
}
Looks like the way I'm generating the signature is no good, but not sure where I'm messing up. Any suggestions?
Here is a proper signature generation method:
And usage:
...