Generally, Cloudinary provides comprehensive API client-libraries in order to save you the hassle of generating the HTTP request and the signature by yourself.
If you still require doing that on your own, you might want to check out how it's done on our client libraries. Below are some references to start from:
api_sign_request(params_to_sign, api_secret)
\Cloudinary::api_sign_request($params_to_sign, $api_secret)
api_sign_request = function(params_to_sign, api_secret)
apiSignRequest(Map<String, Object> paramsToSign, String apiSecret)
api_sign_request(params_to_sign, api_secret)
SignParameters(IDictionary<string, object> parameters)
cld utils api_sign_request $params_to_sign $api_secret
Few more tips:
- The string to sign must consist of a valid Timestamp (UNIX format), your account's
api_secret
and any additional upload parameter in use except:file
,cloud_name
,resource_type
and yourapi_key
. - String to sign must contain all required parameters sorted alphabetically, where the parameter names are separated from their values with an
=
and the parameter/value pairs are joined together with an&
, and end with theapi_secret
. api_secret
should never be revealed to anyone who is not authorized, therefore should never be used on the client-side or inside your native application.- Mobile native applications must either use an unsigned-upload or have a server to process the signature on.
- A signature is only valid for 1 hour since the timestamp it's based on.
- Sanity check - Signing the following string:
"public_id=sample_image×tamp=1315060510abcd"
where `abcd` is theapi_secret
, should result in the following signature:
"b4ad47fb4e25c7bf5f92a20089f9db59bc302313" - More information is available here:
https://cloudinary.com/documentation/upload_images#generating_authentication_signatures
Comments
23 comments
Modeling your sample into a SHA1 digest hex doesn't work with your server. I think there is something missing or out of date. What about the HTTP headers?
William, feel free to share with us your signature generation code (Make sure to remove any secret/private credentials first) so we can further investigate.
You can also do that by opening a support ticket, if privacy is an issue.
For those looking for the Node JS version, it’s actually in a utilities module, so this is how you’d use it:
Thank you for sharing, Thomas!
A Swift code example to do the signature generation:
https://gist.github.com/crspybits/d8d34d18a08eab57c62a0b30f64c4f64
Can the generated signature be used for multiple uploads?
Hi Sunil,
The same signature can be used for uploading multiple files as long as all the parameters remain the same (i.e: tags, folder...).
Thanks. As a signature has a life time of 1 hour, does the multi upload case increase the time limit of signature after each successful upload? Or is it a constant time limit?
The time limit is set at one hour.
Struggling for hours to make a signature on React?
Hi Daniel,
You won't be able to directly generate the signature in React (as it needs your API Secret which should only be used in your backend code), but from your description in your Support Forum post (https://support.cloudinary.com/hc/en-us/community/posts/360049705831-Signed-Widget-Upload-No-Documents-or-Examples-React-Client) and Github comment, it seems you're using the Upload Widget. I've shared more details on this in the Support Forum post, but if this isn't the part you're looking for help with, then please let us know.
I think one thing missing here is where the signature gets utilised.
Am i missing something? Does it become a parameter for the call?
Hi Brian
If you decide to send your own POST request to Cloudinary directly, then you would need to generate the signature manually as well.
The signature should indeed be sent as a parameter to the request.
You could read more about that here
That's not what i'm actually doing. I'm using the SDK to generate the signature like so.
I get a 401 Unauthorized error with a message of "Invalid Signature. String to sign - 'moderation=aws_rek×tamp=#somenumber'
Not much to go from here sadly.
Hi Brian,
Thanks for sharing the additional details.
Looking at the logs I've found the requests you're making.
I'm not sure if you have modified the error message, but the String to sign doesn't include all parameters. You'll notice that the 'folder' is missing.
The complete String to sign would be the below for one of the example uploads.
The signature that was provided wasn't the right one, but if you copy the above String, and sign it via the command line it would generate a correct signature. You should get the following output - 544f31a19ce114ab2a9db35689f5dc31a18c4155
To investigate this further, may I please ask you to first double-check the value of the API Secret that is also passed into the function to sign?
After this, could you please update the value of the payload object to be explicitly:
And ensure it also matches the manually generated signature via the command line. If it matches, then please replace the hardcoded timestamp and use the moment library to generate an up to date one as you've been doing.
Let me know how it goes.
Best regards,
Aleksandar
I have updated my code, I omitted the the folider key and have tried using the sha1 signature I created my self and compared it to the one generated with the SDK.
Even after doing so I get the following error below. I have tried it with postman creating my own post reqest, still no luck at all.
In the postman POST request my body contains the file as a base64 encoded image string, moderation, timestamp, signature, and the api_key.
{
Hi Brian,
Could you please share the command you're running on the terminal to manually generate the signature as well as the one in the code? Please include the exact code + values, just omit the API_SECRET of course.
How did you get 'ae69656c5becd3801f455dc197894f37f01c7ed5', did you generate it via the command line?
Using your latest example, I can get the correct signature by running the following:
Could you please run the above and just replace <API_SECRET> with your actual API Secret? What value do you get?
Let's first try to see why you're getting a wrong signature via the command line, then we'll go back and figure out what's wrong with the code.
Lastly, did you get a chance to run the below code and see what output you get?
Best regards,
Aleksandar
Aleksander, thanks for getting back so quickly.
Here are the results using the exact payload you provided above "WITHOUT Folder".
Hi Brian,
Thanks for sharing these too
Good news, I think I figured out why that happened!
I retried with the same string you're using and the relevant API SECRET but got the correct signature.
Then I removed the last character from your API SECRET and I reproduced the wrong signature you are getting.
May I please ask you to double-check that the last character of the API SECRET is added to the string? You can copy it again from the Account Details section of the Dashboard after signing in to your account.
You can then regenerate the signature in the command line and in the SDK and it should all work correctly!
Best regards,
Aleksandar
Huzza!!!
Wow, smart man.
Thank you, I guess i overlooked verifying the secret since i didn't think I trimmed the end by mistake.
You're very welcome!
As we've removed many dependencies (SDK version / NodeJS / libraries etc) by using the command line we're dealing with a lot less variability and ensured we don't spend time debugging the wrong area. The guess to remove the last character was mainly due to off-by-one errors so I often try removing one or two from the start and the end of the String since if there were any typos they'd be at the start/end and never in the middle. It's quite common and I've run into similar issues myself.
Glad we've found the issue and the upload works now!
Hey,
tried all of the following, still getting the error:
This is my code in Nodejs:
Data is:
I do get a signature, but on the client-side, I get the error mentioned above,
What causes this error?
I doubled checked my cloudinary secret API, doubled checked the values, everything should be fine
Thanks in advance
@Rav
From going off your stackoverflow post. I believe your create-cloudinary-signature endpoint should only be ``` const data = req.query.data; var signature = cloudinary.utils.api_sign_request( data, process.env.CLOUDINARY_API_SECRET ); ``` And for your createUploadWidget, you do not need uploadSignatureTimestamp: timestamp.
Please sign in to leave a comment.