Skip to main content

How to generate a Cloudinary signature on my own?

Comments

23 comments

  • William Jamieson

    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?

    0
  • Nadav Ofir

    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.

    0
  • Thomas Edwards

    For those looking for the Node JS version, it’s actually in a utilities module, so this is how you’d use it:

    cloudinary.utils.api_sign_request(params_to_sign, api_secret)
    0
  • Roee Ben Ari

    Thank you for sharing, Thomas!

    0
  • Christopher Prince

    A Swift code example to do the signature generation:
    https://gist.github.com/crspybits/d8d34d18a08eab57c62a0b30f64c4f64

    0
  • Sunil Kumar

    Can the generated signature be used for multiple uploads?

    0
  • Raya Straus

    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...).

    0
  • Sunil Kumar

    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?

    0
  • Raya Straus

    The time limit is set at one hour. 

    0
  • Arbortree Creations

    Struggling for hours to make a signature on React?

    0
  • Aleksandar Kostadinov

    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.

    0
  • Brian Inoa

    I think one thing missing here is where the signature gets utilised.

    Am i missing something? Does it become a parameter for the call?

    0
  • Ido

    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

    0
  • Brian Inoa

    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&timestamp=#somenumber'

    Not much to go from here sadly.

    0
  • Aleksandar Kostadinov

    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.

    folder=Profiles&moderation=aws_rek&timestamp=1582678665<API_SECRET>

    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

    echo -n "folder=Profiles&moderation=aws_rek&timestamp=1582678665<API_SECRET>" | sha1sum

    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:

    var payload = {
    folder: "Profiles",
    moderation: "aws_rek",
    timestamp: "1582678665"
    };

    cloudinary.utils.api_sign_request(payload, "API_SECRET"));

    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

    0
  • Brian Inoa

    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.

    {

        "error": {
            "message": "Invalid Signature ae69656c5becd3801f455dc197894f37f01c7ed5. String to sign - 'moderation=aws_rek&timestamp=1582813962'."
        }
    }
     
    0
  • Aleksandar Kostadinov

    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:

    echo -n "moderation=aws_rek&timestamp=1582813962<API_SECRET>" | sha1sum

    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?

    var payload = {
    folder: "Profiles",
    moderation: "aws_rek",
    timestamp: "1582678665"
    };

    cloudinary.utils.api_sign_request(payload, "API_SECRET"));

    Best regards,

    Aleksandar

    0
  • Brian Inoa

    Aleksander, thanks for getting back so quickly.

    const payload = {

    moderation: "aws_rek",

    timestamp:"1582678665"

    }

     

    Here are the results using the exact payload you provided above "WITHOUT Folder".

    echo -n "moderation=aws_rek&timestamp=1582813962<API_SECRET>" | shasum
    • sha1sum - ae69656c5becd3801f455dc197894f37f01c7ed5
    echo -n "moderation=aws_rek&timestamp=1582678665<API_SECRET>" | shasum
    • sha1sum - 49ea840d3e7e3576f8aa69a8f2db98eb70e9b826
    cloudinary.v2.utils.api_sign_request({ ...payload }, api_secret);
    • cloudinary.v2.utils.api_sign_request - 49ea840d3e7e3576f8aa69a8f2db98eb70e9b826
    0
  • Aleksandar Kostadinov

    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

    1
  • Brian Inoa

    Huzza!!!

    Wow, smart man.

    Thank you, I guess i overlooked verifying the secret since i didn't think I trimmed the end by mistake.

     

    0
  • Aleksandar Kostadinov

    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!

    0
  • Rav Chesed

    Hey, 

    tried all of the following, still getting the error: 

    Invalid Signature "b4000077c554448649396c31750e27141820693c". String to sign -
    'source=uw&timestamp=1598531294&upload_preset=signed-preset'.

    This is my code in Nodejs:

    router.get("/create-cloudinary-signature", (req, res) => {
      const data = req.query.data;

      // Get the signature using the Node.js SDK method api_sign_request
      var signature = cloudinary.utils.api_sign_request(
        data,
        process.env.CLOUDINARY_API_SECRET
      );

      console.log(signature);

      res.json(signature);

    });

    Data is:

    { timestamp: '1598531294',
    upload_preset: 'signed-preset',
    source: 'uw' }

    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

     

    1
  • Daniel Mendoza

    @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.

    0

Please sign in to leave a comment.