cloudinary icon indicating copy to clipboard operation
cloudinary copied to clipboard

"Error: A Cloudinary API Key is required for signed requests, please make sure your environment variable is set and configured in your environment."

Open tmorgan497 opened this issue 1 year ago • 4 comments

I'm running into an issue getting the CldUploadWidget to work in signed mode. On the client side I have:

                <ClientOnly>
                    <CldUploadWidget
                        v-slot="{ open }"
                        uploadPreset="test"
                        signatureEndpoint="/api/products/get_cloudinary_signature"
                    >
                        <Button label="Upload an Image" @click="open" />
                    </CldUploadWidget>
                </ClientOnly>

and my backend endpoint I have:

// server/api/products/get_cloudinary_signature.ts

import { v2 as cloudinary } from "cloudinary";

export default eventHandler(async (event) => {
    const config = useRuntimeConfig();

    const body = await readBody(event);

    console.log("Request Body:", body);
    console.log("Backend Secret:", config.CLOUDINARY_API_SECRET);

    if (!body || !body.paramsToSign) {
        console.error("Missing paramsToSign in request body.");
        throw createError({
            statusCode: 400,
            statusMessage: "paramsToSign is required.",
        });
    }

    const signature = cloudinary.utils.api_sign_request(
        body.paramsToSign,
        config.CLOUDINARY_API_SECRET,
    );

    console.log("Generated Cloudinary Signature:", signature);

    return { signature };
});

When i manually get the signature from the endpoint, it works fine. The console logs show the api secret and the resulting signature

<template>
                <Button
                    label="Get Cloudinary Signature"
                    @click="printCloudinarySignature"
                />
</template>

<script setup lang="ts">
async function printCloudinarySignature() {
    console.log("Cloudinary API Key:", config.public.cloudinary.apiKey);
    try {
        const timestamp = Math.floor(Date.now() / 1000);
        const paramsToSign = {
            timestamp: timestamp,
            folder: "products",
        };

        const response = await $fetch("/api/products/get_cloudinary_signature", {
            method: "POST",
            body: {
                paramsToSign,
            },
        });
        console.log("Cloudinary Signature:", response.signature);
    } catch (error) {
        console.error("Error fetching Cloudinary signature:", error);
    }
}
</setup>

But the error I'm getting from the widget says I need to set my api key. But i've already verified that the key is setup and working with the debugging code above. Here's my nuxt config:

export default defineNuxtConfig({
    devtools: { enabled: true },
    future: {
        compatibilityVersion: 4,
    },
    runtimeConfig: {
        public: {
            CLOUDINARY_CLOUD_NAME: process.env.CLOUDINARY_CLOUD_NAME,
            CLOUDINARY_API_KEY: process.env.CLOUDINARY_API_KEY,
        },
        CLOUDINARY_API_SECRET: process.env.CLOUDINARY_API_SECRET,
    },

    modules: [
        "@nuxtjs/cloudinary",
    ],

    cloudinary: {
        cloudName: process.env.CLOUDINARY_CLOUD_NAME,
        apiKey: process.env.CLOUDINARY_API_KEY,
        uploadPreset: "test",
    },

});

It's probably a simple mistake, but I can't for the life of me figure out how to get it to work properly. I've tried unsigned mode and it works fine, but I'd like to use signed mode for better access control.

tmorgan497 avatar Oct 05 '24 21:10 tmorgan497

Hey there,

Thanks for reporting this issue. I will take a look at it today :)

Baroshem avatar Oct 07 '24 05:10 Baroshem

Hey, I have released a 3.1.1 patch version with a fix for that. The issue was that the second object in the getUploadWidgetOptions from cloudinary url loader was expecting an apiKey as well.

Could you try with this version? I tried it locally with your code and seemed to work correctly :)

Baroshem avatar Oct 15 '24 09:10 Baroshem

It works fine on my local machine now, but when I deploy it, it doesn't work. However, I've recently learned of the limitations of Cloudflare Workers (this app is deployed to Cloudflare Pages), so it could be because of that. I'm working on switching off of Workers anyways. But regarding the original issue, I believe it's fixed now. Thanks for your help!

And if you're curious, here's the error log from Workers:

10:07:15.205
  POST 500 /api/products/get_cloudinary_signature
[nuxt] [request error] [unhandled] [500],Cannot read properties of undefined (reading 'node')
  at chunks/_/cloudinary.mjs:1:145243  
  at chunks/_/cloudinary.mjs:1:170025

tmorgan497 avatar Oct 15 '24 15:10 tmorgan497

Glad that it is fixed now!

Yes, I think this could be a Cloudflare issue. Thanks for letting us know :)

Baroshem avatar Oct 16 '24 06:10 Baroshem

@Baroshem https://sweepinglacquer17.github.io/secure-coding2/