appwrite / appwrite

Your backend, minus the hassle.
https://appwrite.io
BSD 3-Clause "New" or "Revised" License
45.3k stars 4.01k forks source link

🚀 Feature: Captcha Integration #5384

Open h0lybyte opened 1 year ago

h0lybyte commented 1 year ago

🔖 Feature description

A captcha integration to help combat spam accounts from joining / abusing the self-hosted appwrite platform.

env variables: _APP_CAPTCHA_SERVICE - reCaptcha, hCaptcha, CF ect.. (if its not set, then it _APP_CAPTCHA_KEY - backend key...

Then under the function: function createUser(string $hash, mixed $hashOptions, string $userId, ?string $email, ?string $password, ?string $phone, string $name, Document $project, Database $dbForProject, Event $events): Document Maybe after string $name, we could add ?string $captcha.

Then before processing the try catch, we could put a function to check the string against the captcha service.

🎤 Pitch

With the continuing rise of spam bots, it makes sense to have some defensive layers to protect the user base and save resources.

👀 Have you spent some time to check if this issue has been raised before?

🏢 Have you read the Code of Conduct?

DH-555 commented 1 year ago

Could be great to have it, mainly turnstile or hCaptcha.

Also for apple apps: https://github.com/appwrite/appwrite/issues/4791#issue-1465047196

And for android using Play integrity

That way malicious traffic/abuse caused by bots will be reduced to a really small amount.

Bot traffic, mainly malicious, could not be seen as a problem, but the fact is that 28% of the internet traffic is caused by bots, makes really possible that at some point, they could spam your app or even disrupt your services.

stnguyen90 commented 1 year ago

@h0lybyte, thanks for creating this issue! 🙏🏼

I don't know precisely how captcha integration works, but I would assume the client passes some token to the server, and the server can then validate to see if they passed the captcha or not, right? If so, for now, maybe you can use an Appwrite Function to handle this:

  1. Go to the Auth > Security settings for your project and set Users Limit to 1
    • this will prevent users from being able to create accounts client-side
  2. Add captcha integration client-side
  3. Create an Appwrite Function that accepts the captcha token, email, password, etc.
  4. The Appwrite Function can validate the captcha token and then create the account only if they've passed the captcha check.
DH-555 commented 1 year ago

@stnguyen90 Yes, that's a workaround, but in the case of reads it's going to be needed another new function, so the default data fetching system from appwrite could become completely useless if needed to stop malicious read and write data, since a function is going to replace it.

stnguyen90 commented 1 year ago

in the case of reads it's going to be needed another new function

That's kind of the expected scenario. Any sort of custom behavior should be handled with an Appwrite Function.

Regardless, I think data fetching is related, but should be a separate issue. It would be good to 👍🏼 this issue: https://github.com/appwrite/appwrite/issues/5060.

h0lybyte commented 1 year ago
  1. Auth > Security settings for your project and set Users Limit to 1

Wouldnt this then limit the SSO? i.e lets say you have a captcha for the register but dont want to have it for SSO?

minecrawler commented 1 year ago

I don't know precisely how captcha integration works

Captchas work like this:

  1. you register with a Captcha service
  2. When there's a new user request, on the server side, you get a token from the captcha service
  3. you inject captcha code into your form. The code will do its thing.
  4. When the user submits the form, you call the captcha service with the token from 2) and ask if it was verified
  5. If it was verified: GOOD! If not, send an error.

Usually, captcha client code gives you a client API to also check if it was verified, so you can still disable the submit button while waiting for a catcha (UX!). The good thing is that all you need to do is pass a token around, and the captcha can be as complex as it wants.

In the case of appwrite, it would be good to offer some kind of integration by providing a code library which needs to be delivered to the client and can take over things like captcha integration. Or alteratively to offer integration with a number of popular captcha services and leave the client side to the customer.

On a side-note, captchas can be broken by captcha farms (humans solving captchas for money) and AI (the "granny locket method" was big in the news just the other day). Captchas will keep bots out, but script kiddies and BHs can still easily crack it.

Also, is there a status update?

maks-io commented 5 months ago

@h0lybyte, thanks for creating this issue! 🙏🏼

I don't know precisely how captcha integration works, but I would assume the client passes some token to the server, and the server can then validate to see if they passed the captcha or not, right? If so, for now, maybe you can use an Appwrite Function to handle this:

  1. Go to the Auth > Security settings for your project and set Users Limit to 1

    • this will prevent users from being able to create accounts client-side
  2. Add captcha integration client-side
  3. Create an Appwrite Function that accepts the captcha token, email, password, etc.
  4. The Appwrite Function can validate the captcha token and then create the account only if they've passed the captcha check.

Can you please tell me if step 3 + 4 are also possible with a custom node backend using node-appwrite or is this limited to appwrite functions only? I have tried to do it via my own node backend but i am currently receiving the user_count_exceeded error, which makes me assume that it is not possible?

maks-io commented 5 months ago

Please ignore my false alert, i confused the Account service with the Users one. With the latter it works properly.