Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
tmorgan497 opened this issue Oct 5, 2024 · 4 comments · Fixed by #245 · May be fixed by #246
Assignees
Labels
question Further information is requested
Milestone

Comments

@tmorgan497
Copy link

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 tmorgan497 added the question Further information is requested label Oct 5, 2024
@Baroshem
Copy link
Collaborator

Baroshem commented Oct 7, 2024

Hey there,

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

@Baroshem Baroshem self-assigned this Oct 15, 2024
Baroshem added a commit that referenced this issue Oct 15, 2024
@Baroshem
Copy link
Collaborator

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 added a commit that referenced this issue Oct 15, 2024
@Baroshem Baroshem linked a pull request Oct 15, 2024 that will close this issue
@Baroshem Baroshem added this to the 4.0.0 milestone Oct 15, 2024
@tmorgan497
Copy link
Author

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

@Baroshem
Copy link
Collaborator

Glad that it is fixed now!

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants