-
Notifications
You must be signed in to change notification settings - Fork 45.8k
feat(platform): Add captcha to login, signup and password reset pages #9847
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
Merged
Bentlybro
merged 33 commits into
dev
from
bently/secrt-1169-implement-captcha-on-sign-up
May 7, 2025
Merged
Changes from 26 commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
7b65f63
Add captcha to login, signup and password reset pages
Bentlybro ecc9ba7
add secrets config
Bentlybro e79a103
fixes
Bentlybro 31b0483
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro 50c5ba4
Prettier
Bentlybro df3a579
format
Bentlybro 1de0bcf
add missing parameters
Bentlybro b2f2873
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro ac102d1
Update autogpt_platform/backend/backend/server/v2/turnstile/models.py
Bentlybro 4f98b5d
add turnstile_site_key to settings.py + rename secret_key to turnsti…
Bentlybro 140df10
Update settings.py
Bentlybro 797a383
add new line to ``.env.example``
Bentlybro 2ca030e
make turnstileToken required
Bentlybro b8b9a9e
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro cca20e1
prettier
Bentlybro 4ac6409
fix "Type 'undefined' is not assignable to type 'string'."
Bentlybro 2cbed54
format
Bentlybro 5c14e55
skip captcha if not BehaveAs = CLOUD
Bentlybro 3467dd1
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro 7a9d249
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro 1b4451f
remove turnstile_site_key from settings.py
Bentlybro f018c02
add CLOUDFLARE_TURNSTILE_VERIFY_URL to backend ``.env``
Bentlybro b97a1d6
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro 40029ba
updates
Bentlybro 9dea8ab
Merge branch 'bently/secrt-1169-implement-captcha-on-sign-up' of http…
Bentlybro 2da4bd5
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro 29689d6
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro dd90903
Add system to reset turnstile token on failed login/register/password…
Bentlybro 8449e28
prettier
Bentlybro 1f4a72d
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro 54a1a04
fix not peoperly refreshing on failed login ect
Bentlybro e08889e
Merge branch 'dev' into bently/secrt-1169-implement-captcha-on-sign-up
Bentlybro ab46474
prettier
Bentlybro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
30 changes: 30 additions & 0 deletions
30
autogpt_platform/backend/backend/server/v2/turnstile/models.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel, Field | ||
|
||
|
||
class TurnstileVerifyRequest(BaseModel): | ||
"""Request model for verifying a Turnstile token.""" | ||
|
||
token: str = Field(description="The Turnstile token to verify") | ||
action: Optional[str] = Field( | ||
default=None, description="The action that the user is attempting to perform" | ||
) | ||
|
||
|
||
class TurnstileVerifyResponse(BaseModel): | ||
"""Response model for the Turnstile verification endpoint.""" | ||
|
||
success: bool = Field(description="Whether the token verification was successful") | ||
error: Optional[str] = Field( | ||
default=None, description="Error message if verification failed" | ||
) | ||
challenge_timestamp: Optional[str] = Field( | ||
default=None, description="Timestamp of the challenge (ISO format)" | ||
) | ||
hostname: Optional[str] = Field( | ||
default=None, description="Hostname of the site where the challenge was solved" | ||
) | ||
action: Optional[str] = Field( | ||
default=None, description="The action associated with this verification" | ||
) |
108 changes: 108 additions & 0 deletions
108
autogpt_platform/backend/backend/server/v2/turnstile/routes.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import logging | ||
|
||
import aiohttp | ||
from fastapi import APIRouter | ||
|
||
from backend.util.settings import Settings | ||
|
||
from .models import TurnstileVerifyRequest, TurnstileVerifyResponse | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
router = APIRouter() | ||
settings = Settings() | ||
|
||
|
||
@router.post("/verify", response_model=TurnstileVerifyResponse) | ||
async def verify_turnstile_token( | ||
request: TurnstileVerifyRequest, | ||
) -> TurnstileVerifyResponse: | ||
""" | ||
Verify a Cloudflare Turnstile token. | ||
This endpoint verifies a token returned by the Cloudflare Turnstile challenge | ||
on the client side. It returns whether the verification was successful. | ||
""" | ||
logger.info(f"Verifying Turnstile token for action: {request.action}") | ||
return await verify_token(request) | ||
|
||
|
||
async def verify_token(request: TurnstileVerifyRequest) -> TurnstileVerifyResponse: | ||
""" | ||
Verify a Cloudflare Turnstile token by making a request to the Cloudflare API. | ||
""" | ||
# Get the secret key from settings | ||
turnstile_secret_key = settings.secrets.turnstile_secret_key | ||
turnstile_verify_url = settings.secrets.turnstile_verify_url | ||
|
||
if not turnstile_secret_key: | ||
logger.error("Turnstile secret key is not configured") | ||
return TurnstileVerifyResponse( | ||
success=False, | ||
error="CONFIGURATION_ERROR", | ||
challenge_timestamp=None, | ||
hostname=None, | ||
action=None, | ||
) | ||
|
||
try: | ||
async with aiohttp.ClientSession() as session: | ||
payload = { | ||
"secret": turnstile_secret_key, | ||
"response": request.token, | ||
} | ||
|
||
if request.action: | ||
payload["action"] = request.action | ||
|
||
logger.debug(f"Verifying Turnstile token with action: {request.action}") | ||
|
||
async with session.post( | ||
turnstile_verify_url, | ||
data=payload, | ||
timeout=aiohttp.ClientTimeout(total=10), | ||
) as response: | ||
if response.status != 200: | ||
error_text = await response.text() | ||
logger.error(f"Turnstile API error: {error_text}") | ||
return TurnstileVerifyResponse( | ||
success=False, | ||
error=f"API_ERROR: {response.status}", | ||
challenge_timestamp=None, | ||
hostname=None, | ||
action=None, | ||
) | ||
|
||
data = await response.json() | ||
logger.debug(f"Turnstile API response: {data}") | ||
|
||
# Parse the response and return a structured object | ||
return TurnstileVerifyResponse( | ||
success=data.get("success", False), | ||
error=( | ||
data.get("error-codes", None)[0] | ||
if data.get("error-codes") | ||
else None | ||
), | ||
challenge_timestamp=data.get("challenge_timestamp"), | ||
hostname=data.get("hostname"), | ||
action=data.get("action"), | ||
) | ||
|
||
except aiohttp.ClientError as e: | ||
logger.error(f"Connection error to Turnstile API: {str(e)}") | ||
return TurnstileVerifyResponse( | ||
success=False, | ||
error=f"CONNECTION_ERROR: {str(e)}", | ||
challenge_timestamp=None, | ||
hostname=None, | ||
action=None, | ||
) | ||
except Exception as e: | ||
logger.error(f"Unexpected error in Turnstile verification: {str(e)}") | ||
return TurnstileVerifyResponse( | ||
success=False, | ||
error=f"UNEXPECTED_ERROR: {str(e)}", | ||
challenge_timestamp=None, | ||
hostname=None, | ||
action=None, | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.