[Marketplace] Cloudflare Turnstile Widget

Hello everyone, I saw that implementing any type of Captcha in WeWeb is quite a challenge for y’all. I’ve worked on this for one of my partners recently and decided to share it with you all actually.

I’ve just released a Marketplace Custom Coded Element that solves this once for all. You can now import Cloudflare Turnstile simply by dragging and dropping the widget to your WeWeb project (and of course setting your token). It also has a possibility to:

  • Refresh the widget - this removes and adds a new widget, effectively generating a new captcha via the Execute component action → Re-render Turnstile
  • Change language - you can select any of the many languages that are available by Cloudflare (such as Farsi, Chinese, Bulgarian etc. there is really many)
  • Change the theme - Light mode, Dark mode, or Automatic selection of the theme

It exposes the token as a variable so you can bind it in WeWeb without all the work to even get it into WeWeb.

You can find the widget in the marketplace, there also is an interactive demo.
https://marketplace.weweb.io/libraries/d318f23f-789f-4229-9460-8d547cfa9f07/

6 Likes

Congratulations for publishing the component! :tada:
Some feedback (I hope it can be useful):

  • [Brotilities Turnstile] logs can be debug level logs to allow easy filtering in the dev tools
  • a global property to disable every log is useful if you don’t want to show logs in the published app, make it bindable so you can easily keep logs for dev and staging)
  • since you are opting for explicitly rendering the widget you may want to disable implicit rendering by appending the parameter render=explicit to the script url
  • not sure if it is intentional, but there is an error because the script is loaded with instructions to run a callback (_turnstileCb) that doesn’t exists in the global scope

Thanks for the feedback, I pushed the Debug property, but i haven’t re-published :smiley: So yeah, fixed but not. As for the other two, they’re actually connected, in the docs, if you have a look, the explicitly loading can happen with a callback only in the string, which was the approach I went for before anything else. It didn’t work, but I forgot to swap it for the render = explicit indeed. Great catch :slight_smile: I for some reason didn’t see the error at first. Will be fixed in a few, thanks again, useful as usually :slight_smile:

2 Likes

Hi Broberto,

This is a great component that has made my work much easier, but I’m running into a few problems with its implementation. It’s probably more of a problem with the Supabase Auth plugin from WeWeb, and I’m sure you’ve encountered it too, so I just want to make sure I’ve chosen the right approach.

When a user wants to resend the OTP code to verify their email, if I select the action from the plugin, I get an error saying that I didn’t enter the captcha “captcha verification process failed”, which this action doesn’t even allow me to do, or rather, there is nowhere to enter the captcha token - I managed to get around this by re-registering the user = they get the OTP code again.

But I ran into a problem with “forgot password” and “change password”—is the solution to use the Rest API? Is it as simple to implement as when I call the Supabase function using the Rest API, or is there something I need to watch out for?

Thank you in advance for your response.

1 Like

Hi, I can see the issue. In the Supabase plugin from WeWeb it sometimes happens, that there is bugs where you either can’t use settings that are exposed, or they aren’t exposed at all - I’ve noticed this too. As you correctly said it’s either REST API, or you could use the Supabase instance which WeWeb exposes:

// Custom JavaScript Workflow Action
// ----------------------------------------------------

const supabase = wwLib.wwPlugins.supabase.instance

// Your OTP here
const { data, error } = await supabase.auth.signInWithOtp({
  phone: '+13334445555',
  options: {
  captchaToken: [your_variable_here]
  }
})

// ----------------------------------------------------

For the full reference, check out Supabase Docs, JavaScript API Reference | Supabase Docs

1 Like

Oh, I didn’t know about the instance. It was much more convenient to implement, and it works exactly as it should. Thanks!

1 Like

Hi Broberto, it doesn’t seem like you deployed the debug property, right?

Hi, sadly I haven’t been able to update the component, because WeWeb was unable to solve (since then) to fix a bug I’m having - any update being pushed to the component doesn’t reflect in the editor. After weeks of asking for updates, I eventually gave up on asking. So the component currently comes as is, as I’m unable to work on it.

1 Like

Hi Broberto,
We enabled Captcha with your widget, and it works great.
But in our app, we have a page where anonymous users can interact.
And it fails since wwLib.wwPlugins.supabaseAuth.publicInstance.auth.signInAnonymously() is now waiting for a captcha token.
Do you have some piece of advice on how to resolve the issue (obviously we don’t want to add a captcha to an anonymous page)?

Hi, you need to either use the wwLib.wwPlugins instance to use the anonymous sign-in manually (with code) and pass in the token. There is many topics on the forum mentioning how to work around roadblocks with this pattern.

Or an another option would be to open a ticket and hope your issue is important enough for WeWeb to consider it (and fix it within a reasonable time).

Also thanks for purchasing the component and I’m glad it works for you :slight_smile:

To my knowledge, the signInAnonymously() function doesn’t take the captcha token as a parameter.


It might not in WeWeb, because it’s not implemented. But the underlying library definitely does. Or at least the latest version of it. That also might be a culprit, an outdated version of Supabase wouldn’t be a new thing in the WeWeb’s plugin, I also had to wait like a month+ for them to roll it out with the new version when I needed it last time :slight_smile:

1 Like

Thanks Broberto, it works fine with:
const { data, error } = await wwLib.wwPlugins.supabaseAuth.publicInstance.auth.signInAnonymously({options: {captchaToken: your_token || undefined}});

1 Like

Amazing! Glad to see you did it :folded_hands::fire: