cloudinary / cloudinary_ios

Cloudinary iOS SDK
MIT License
165 stars 106 forks source link

Missing required parameter - api_key #71

Closed JonathanLu2393 closed 7 years ago

JonathanLu2393 commented 7 years ago

I am trying to attempted a signed upload, but I get the error message "Missing required parameter - api_key"

Here is the code I am running.

    let pngRepresentation = UIImagePNGRepresentation(image)
    let forUpload = pngRepresentation as Data

    let config = CLDConfiguration(cloudName: cloud_name, apiKey: api_key, apiSecret: nil)
    let cloudinary = CLDCloudinary(configuration: config)

    let timestamp = NSNumber(value: timestamp)
    let signature = CLDSignature(signature: imageSignature!.signature!, timestamp: timestamp)

    let params = CLDUploadRequestParams()
    params.setSignature(signature)
    params.setPublicId(public_id)
    params.setUploadPreset(uploadPreset)

    cloudinary.createUploader().signedUpload(data: forUpload, params: params, progress: nil) {
        result, err in

        print(err)
    }

My CLDCloudinary instance cloudinary has the api_key in it and there is no option to add it to params.

JonathanLu2393 commented 7 years ago

Seems like it was a known issue. The key wasnt getting pulled from config.

params.setParam("api_key", API_KEY)

The line of code above solved it.

However, I am getting a new error

Invalid Signature ea7c4b7df87f211cc40696268b5d1d60a0b9b4a2.

String to sign - 'public_id=student56e092833b7713110018e2c9&timestamp=1&upload_preset=profilepic'.

As you see from above, I do params.SetSignature, but it does not seem to sign my upload.

oferZemingo commented 7 years ago

There's an issue that changes the timestamp, instead of using CLDSignature for now you can workaround it by setting its properties manually:

params.setParam("api_key", YOUR_API_KEY)
params.setParam("signature", YOUR_SIGNATURE)
params.setParam("timestamp", YOUR_TIMESTAMP_AS_STRING)
JonathanLu2393 commented 7 years ago

The workaround did not work for me.

If do

params.setParam("timestamp", MY_TIMESTAMP)    

while my timestamp value is "1487182818724", I get the error message

Invalid Signature 09d9939be7dac078780a54c22c5f43e85b73555b. String to sign -'timestamp=1487182920'.

Is the timestamp supposed to be the same?

oferZemingo commented 7 years ago

Yes, you should pass the same timestamp that was used to generate the signature, be sure you pass the timestamp as a string.

JonathanLu2393 commented 7 years ago

I have tried this.

The problem still persists.

The error message string has a different timestamp than the one I used.

oferZemingo commented 7 years ago

Not sure how you're generating your signature, try using the timestamp in seconds and not milliseconds.

JonathanLu2393 commented 7 years ago

No luck with that solution either.

Heres what Im doing.

First my API creates a signature and timestamp.

    var timestamp = new Date().getTime()/1000;
    var timestampInt =  parseInt(timestamp);
    var stringToSHA = "public_id=" + publicId + "&timestamp=" + timestampInt.toString() + api_secret;

    var signature = sha1(stringToSHA);

It is then passed to my iOS app, to create the upload request, within the params

    let params = CLDUploadRequestParams()
    params.setParam("api_key", value: apiKey)
    params.setParam("signature", value: signature)
    params.setParam("timestamp", value: String(timestampInt))

Then I try to upload my image data with the following request.

    print("DEBUG: Signature = \(signature)")
    print("DEBUG: TimeStamp = \(timestamp)")
    cloudinary.createUploader().signedUpload(data: forUpload, params: params, progress: nil) {
        result, err in
    {

This produces image

As you can see, my timestamp that I append to params, stays the same. But the error message that I get back shows a different timestamp each time.

Am I generating my timestamp wrong? This was working on previous versions of cloudinary. It seems that the error message I am getting is the current timestamp.

oferZemingo commented 7 years ago

The only way the SDK will override your timestamp is if you have your apiSecret set as part of your CLDConfiguration, if thats the case there's no need to generate the signature on your server and pass it to the client, you can simply call signedUpload(...) without setting the signature param and the SDK will generate a signature for you and add it to the call.

JonathanLu2393 commented 7 years ago

My apiSecret is apart of my CLDConfiguration.

let config = CLDConfiguration(cloudName: cloud_name, apiKey: apiKey, apiSecret: api_secret)
let cloudinary = CLDCloudinary(configuration: config)

The above is what I am currently doing.

Commenting out

params.setParam("signature", value: signature)
params.setParam("timestamp", value: String(timestampInt))

Still gives the same result with the error message:

Invalid Signature 21f5b899ac405f7a23c0adbd019f1cda1fd13ae8. String to sign - 'timestamp=1487201943'.
ofermeroz commented 7 years ago

Remove setting the api_key as well, if you're not setting any other params to CLDUploadRequestParams you can drop it:

cloudinary.createUploader().signedUpload(data: forUpload, completionHandler: { (result, err) in

        })
JonathanLu2393 commented 7 years ago

I am using params for public_id and upload_preset, but removing the other params worked.

Thank you very much.