If you don't find an answer, please click here to post your question.
Reply
Member
Posts: 4
Registered: ‎11-28-2016
Accepted Solution

Video Upload Signing - Objective C using Ooyala API

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!


Accepted Solutions
Community Manager
Posts: 119
Registered: ‎02-03-2014

Re: Video Upload Signing - Objective C using Ooyala API

Hi, Andreas. These are the pre-build libraries https://github.com/ooyala/objective-c-v2-sdk we talked about over the phone.


Please use those and if it is still not working for you, please grab some network logs using https://www.charlesproxy.com/

Let me know the output.

Thanks.

View solution in original post


All Replies
Community Manager
Posts: 119
Registered: ‎02-03-2014

Re: Video Upload Signing - Objective C using Ooyala API

Hi, AndreasApp. what's the network response you are getting here? Could you please attach a network session?

That would be a great way to start here.

Thanks!
Member
Posts: 4
Registered: ‎11-28-2016

Re: Video Upload Signing - Objective C using Ooyala API

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! :)

Community Manager
Posts: 119
Registered: ‎02-03-2014

Re: Video Upload Signing - Objective C using Ooyala API

Hi, I really need the network logs taken on the moment you perform the API request to see the point of failure.

I noted this may be a high priority for you, if that's the case, I suggest you file a high priority ticket on http://help.ooyala.com/contact to get better SLAs in terms of responses from our support team.

Thank you.
Member
Posts: 4
Registered: ‎11-28-2016

Re: Video Upload Signing - Objective C using Ooyala API

[ Edited ]

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!

Member
Posts: 4
Registered: ‎11-28-2016

Re: Video Upload Signing - Objective C using Ooyala API

I've tried to use the TechSupport too, but I can't login with my credentials.. So unfortunately that won't work for me..

Community Manager
Posts: 119
Registered: ‎02-03-2014

Re: Video Upload Signing - Objective C using Ooyala API

Hi, Andreas. These are the pre-build libraries https://github.com/ooyala/objective-c-v2-sdk we talked about over the phone.


Please use those and if it is still not working for you, please grab some network logs using https://www.charlesproxy.com/

Let me know the output.

Thanks.
Occasional Advisor
Posts: 9
Registered: ‎01-03-2018

Re: Video Upload Signing - Objective C using Ooyala API

 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??

 

 

Ooyalan
Posts: 8
Registered: ‎10-09-2017

Re: Video Upload Signing - Objective C using Ooyala API

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

Occasional Advisor
Posts: 9
Registered: ‎01-03-2018

Re: Video Upload Signing - Objective C using Ooyala API

Thanks pperez! The code need to be updated but I get a solution with this code.