|
Turn on suggestions
![]() Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type. | |
If you don't find an answer, please click here to post your question.
|
11-28-2016 08:36 PM
Hi @ all,
I'm searching for the correct way to get the correct signing for my upload.
I get different results by using the command line and the Scratchpad. I'm using the Ooyala API (little bit modified, because it won't work in my Project) at the moment.
Is there a good example how to add the json-body to the signing? I think creating the NSData by using the
NSJSONSerialization with the option "NSJSONWritingPrettyPrinted" does not work very well for the signing purpose. I attached my code to this.
I'm using AFNetworking for the HTTPRequest with the generated Link of the OoyalaAPI.
Ooyala API:
#import "OoyalaAPI.h" #import <CommonCrypto/CommonDigest.h> #define ROUNDING_WINDOW 300 @implementation OoyalaAPI /// <summary> /// Takes in the necessary parameters to build a V2 signature for the Ooyala API /// Use generateEncodedSignedURLWithHTTPMethod /// </summary> /// <param name="apiKey"> /// The API key for the Ooyala account to generate the URL for. You can find this key in the Developers tab in Backlot /// </param> /// <param name="secretKey"> /// The Secret key for the Ooyala account to generate the URL for. You can find this key in the Developers tab in Backlot /// </param> /// <param name="HTTPMethod"> /// The method to be used for the request. Possible values are: GET, POST, PUT, PATCH or DELETE /// </param> /// <param name="requestPath"> /// The path to use for the request /// </param> /// <param name="queryStringParameters"> /// A dictionary containing the list of parameters that will be included in the request. /// </param> /// <param name="requestBody"> /// An NSData containing the JSON representation of the data to be sent on the request. If there's no body for the request, just include an empty NSData object /// </param> /// <returns> /// The signed URL to be used in the HTTP request. /// </returns> /*+ (NSString *)URLEncodeString:(NSString *)string { return [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; }*/ + (NSString *)URLEncodeString:(NSString *)string { CFTypeRef URLEncodedCFType = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)string, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", kCFStringEncodingUTF8); NSString *URLEncodedString = [NSString stringWithFormat:@"%@",URLEncodedCFType]; CFRelease(URLEncodedCFType); return URLEncodedString; } + (NSString *)generateEncodedSignatureWithHTTPMethod:(NSString *)HTTPMethod requestPath:(NSString *)requestPath queryStringParameters:(NSDictionary *)queryStringParameters secretKey:(NSString *)secretKey apiKey:(NSString *)apiKey andRequestBody:(NSData *)requestBody { // // Generate stringToSign // //Concatenate first parameters to stringToSign NSString *stringToSign = [NSString stringWithFormat:@"%@%@%@",secretKey,HTTPMethod,requestPath]; //Generate mutable dictionary for parameters NSMutableDictionary *parametersDictionary = [NSMutableDictionary dictionaryWithDictionary:queryStringParameters]; //Expires //Generate and add expires parameter if not already present //Default expires time: 5min = 300s if(![parametersDictionary objectForKey:@"expires"]){ NSNumber *expiresWindow = [NSNumber numberWithInt:300]; NSUInteger timestamp = (long)[[NSDate date] timeIntervalSince1970] + [expiresWindow intValue]; timestamp += [[NSNumber numberWithInt:ROUNDING_WINDOW] intValue] - (timestamp % [[NSNumber numberWithInt:ROUNDING_WINDOW] intValue] ); [parametersDictionary setValue:[NSString stringWithFormat:@"%lu", (unsigned long)timestamp] forKey:@"expires"]; } //Add api_key parameter [parametersDictionary setValue:[NSString stringWithFormat:@"%@", apiKey] forKey:@"api_key"]; //Sort parameters and append to stringToSign NSArray *keys = [[parametersDictionary allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; for (NSUInteger i = 0; i < [keys count]; i++) { NSString *key = [keys objectAtIndex:i]; NSString *value = [parametersDictionary objectForKey:key]; stringToSign = [stringToSign stringByAppendingFormat:@"%@=%@", key, value]; } //Append Body NSString *requestBodyString = [[NSString alloc] initWithData:requestBody encoding:NSUTF8StringEncoding]; stringToSign = [stringToSign stringByAppendingFormat:@"%@",requestBodyString]; // // Generate signature from stringToSign // unsigned char hashedChars[32]; NSUInteger i; //Generate SHA-256 in Base64 CC_SHA256([stringToSign UTF8String], [stringToSign lengthOfBytesUsingEncoding:NSUTF8StringEncoding], hashedChars); NSData *hashedData = [NSData dataWithBytes:hashedChars length:32]; NSString *signature = [hashedData base64EncodedStringWithOptions:0]; //Truncate signature to 43 characters signature = [signature substringToIndex:(NSUInteger)43]; //Remove from signature trailing = signs for (i = [signature length] - 1; [signature characterAtIndex:i] == '='; i = [signature length] - 1) { signature = [signature substringToIndex:i]; } //URL-encode signature return [OoyalaAPI URLEncodeString:signature]; } + (NSURL *)generateEncodedSignedURLWithHTTPMethod:(NSString *)HTTPMethod requestPath:(NSString *)requestPath queryStringParameters:(NSDictionary *)queryStringParameters apiKey:(NSString *)apiKey secretKey:(NSString *)secretKey andRequestBody:(NSData *)requestBody { //Append first parts of URLString NSString *URLString = [NSString stringWithFormat:@"%@%@",@"https://api.ooyala.com",requestPath]; /** * Process queryStringParameters */ //Generate mutable dictionary for parameters NSMutableDictionary *parametersDictionary = [NSMutableDictionary dictionaryWithDictionary:queryStringParameters]; //Expires //Generate and add expires parameter if not already present //Default expires time: 5min = 300s if(![parametersDictionary objectForKey:@"expires"]){ NSNumber *expiresWindow = [NSNumber numberWithInt:15]; NSUInteger timestamp = (long)[[NSDate date] timeIntervalSince1970] + [expiresWindow intValue]; timestamp += [[NSNumber numberWithInt:ROUNDING_WINDOW] intValue] - (timestamp % [[NSNumber numberWithInt:ROUNDING_WINDOW] intValue] ); [parametersDictionary setValue:[NSString stringWithFormat:@"%lu", (unsigned long)timestamp] forKey:@"expires"]; } //Add api_key parameter [parametersDictionary setValue:[NSString stringWithFormat:@"%@", apiKey] forKey:@"api_key"]; //Sort parameters and append to URLString NSArray *keys = [[parametersDictionary allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; for (NSUInteger i = 0; i < [keys count]; i++) { NSString *key = [keys objectAtIndex:i]; NSString *value = [parametersDictionary objectForKey:key]; NSString *format = (i==0)?@"?%@=%@":@"&%@=%@"; URLString = [URLString stringByAppendingFormat:format, [OoyalaAPI URLEncodeString:key], [OoyalaAPI URLEncodeString:value]]; } //Append the signature URLString = [URLString stringByAppendingFormat:@"&signature=%@",[self generateEncodedSignatureWithHTTPMethod:HTTPMethod requestPath:requestPath queryStringParameters:queryStringParameters secretKey:secretKey apiKey:apiKey andRequestBody:requestBody]]; return [NSURL URLWithString:URLString]; } @end
And my function to call the API:
// Ooyala Account defines #define OoyalaAPIKey @"OoyalaAPIKey" #define OoyalaSecret @"OoyalaSecret" #define videoUploadSize 100000 /* The Ooyala Backend Connection for video up- and download */ #pragma mark - Ooyala Backend +(void)requestSignedVideoURL:(Video *)video { // Build the attributes for the post request NSMutableDictionary *parameter = [[NSMutableDictionary alloc] init]; [parameter setValue:video.fileName forKey:@"name"]; //todo [parameter setValue:video.fileName forKey:@"file_name"]; [parameter setValue:@"video" forKey:@"asset_type"]; [parameter setValue:[NSString stringWithFormat:@"%d", video.fileSize] forKey:@"file_size"]; [parameter setValue:[NSString stringWithFormat:@"%i", videoUploadSize] forKey:@"chunk_size"]; // Perform the request to the ooyala backend NSError *error = nil; NSData *jsonParameters = [NSJSONSerialization dataWithJSONObject:parameter options:0 error:&error]; NSURL *finalURL = [OoyalaAPI generateEncodedSignedURLWithHTTPMethod:@"POST" requestPath:@"/v2/assets" queryStringParameters:nil apiKey:OoyalaAPIKey secretKey:OoyalaSecret andRequestBody:jsonParameters]; // ... Sending the Request by using AFNetworking and the configured httpSessionManager as a POST method ... }
Looking forward for some help!
Cheers!
12-06-2016 03:46 PM
11-29-2016 07:17 AM
11-29-2016 12:27 PM
I'm getting the Error code 400 (bad request).
I also used postman for testing my request (the post route, attributes and body) which response that the signing is invalid.
How do I have to append the json body to the request, so that the correct signing will be processed?
Most of the time, the signing was correct (checked it by manually processing the signing in the terminal), but the respomse was also error code 400 - bad request (signing is invalid).
Thanks for your help! :)
11-30-2016 11:21 AM
12-04-2016 02:24 PM - edited 12-04-2016 02:27 PM
Sorry for the late response. I've got another project, which takes some time..
I'm just sending the following:
POST 'https://api.ooyala.com/v2/assets?api_key=*MYAPIKEY*&expires=1480890300&signature=*SIGNATURE*
And response this error:
error NSError * domain: @"com.alamofire.error.serialization.response" - code: 18446744073709550605 0x00006100000515b0
_userInfo __NSDictionaryI * 4 key/value pairs 0x00006100000e3600
[0] (null) @"com.alamofire.serialization.response.error.response" : (no summary)
[1] (null) @"NSErrorFailingURLKey" : @"https://api.ooyala.com/v2/assets?api_key=*MYAPIKEY*&expires=1480890300&signature=*SIGNATURE"
[2] (null) @"com.alamofire.serialization.response.error.data" : 32 bytes
[3] (null) @"NSLocalizedDescription" : @"Request failed: bad request (400)"
{ URL: https://api.ooyala.com/v2/assets?api_key=*MYAPIKEY*&expires=1480890300&signature=*SIGNATURE* } { status code: 400, headers {
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Sun, 04 Dec 2016 22:20:36 GMT";
"Ooyala-Request-Id" = b4da06c6a3054f3cb540a172d1fd5f9e;
"Ooyala-Server-Id" = "i-2e7ec9fd";
Server = "nginx/1.2.7";
Status = "400 Bad Request";
"Transfer-Encoding" = Identity;
} }, NSErrorFailingURLKey=https://api.ooyala.com/v2/assets?api_key=*MYAPIKEY*&expires=1480890300&signature=*SIGNATURE*
Is this what you need? I hope that helps..
Thanks for your help!
12-04-2016 03:34 PM
I've tried to use the TechSupport too, but I can't login with my credentials.. So unfortunately that won't work for me..
12-06-2016 03:46 PM
01-03-2018 10:39 AM
I have the same problem and the code of https://github.com/ooyala/objective-c-v2-sdk is old. It have deprecated sentences. Can you give me any solution, please??
01-04-2018 09:35 AM
Hi fuentesplayer!
Thank you for contacting us! Please look at the following link from our Help Center and let me know if this help you solve your problem:
Sample Signature Code (Objective C)
https://help.ooyala.com/video-platform/api/signature_objectivec.html
Thank you,
Ooyala Technical Support Team
01-11-2018 04:30 AM
Thanks pperez! The code need to be updated but I get a solution with this code.