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

feat: Implemented reCAPTCHA v3 #226

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions backend/routes/auth_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from typing import Annotated
from datetime import timedelta, datetime,date
from enum import Enum
from utils import verify_recaptcha


class CityChoice(str,Enum):
Expand Down Expand Up @@ -105,6 +106,12 @@ async def get_current_patient(token: Annotated[str, Depends(oauth2_bearer)]):
@auth_router.post("/signup", status_code=status.HTTP_201_CREATED)
async def create_user(db: db_dependency,
create_patient_request: CreatePatientRequest):

is_human = await verify_recaptcha(create_patient_request.recaptcha_token)
if not is_human:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
detail='Recaptcha verification failed.')

patient_id = str(uuid4())
current_time = datetime.utcnow()
create_user_model = Patient(
Expand All @@ -128,6 +135,12 @@ async def create_user(db: db_dependency,
@auth_router.post("/login", response_model=Token)
async def login_for_access_token(form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
db: db_dependency):

recaptcha_token = form_data.__dict__.get('recaptcha_token')
if not recaptcha_token or not await verify_recaptcha(recaptcha_token):
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
detail='Recaptcha verification failed.')

user = authenticate_patient(form_data.username, form_data.password, db)
if not user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
Expand Down
13 changes: 13 additions & 0 deletions backend/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# utils.py
import httpx

async def verify_recaptcha(token: str) -> bool:
url = "https://www.google.com/recaptcha/api/siteverify"
payload = {
'secret': "6LfsY-8pAAAAANjrT-Y7an1-Va3NkUTgDp9Y_oHS",
'response': token
}
async with httpx.AsyncClient() as client:
response = await client.post(url, data=payload)
result = response.json()
return result.get("success", False)
26 changes: 23 additions & 3 deletions src/Pages/LoginPage.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import React, { useState } from "react";
import { IoEye, IoEyeOff } from "react-icons/io5";
import { Link } from "react-router-dom";
import { Helmet } from "react-helmet";

function LoginPage() {
const [passVis, setPassVis] = useState(false);

const onSubmit = (token) => {
document.getElementById("login-form").submit();
};
return (
<>
<Helmet>
<script src="https://www.google.com/recaptcha/api.js" defer></script>
</Helmet>
<section class="bg-zinc-50 py-8 min-h-screen login">
<div class="flex flex-col items-center max-w-[28rem] justify-center px-6 py-8 mx-auto mt-7 lg:py-8">
<a
Expand All @@ -20,7 +28,7 @@ function LoginPage() {
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl">
Sign in to your account
</h1>
<form class="space-y-4 md:space-y-6" action="#">
<form class="space-y-4 md:space-y-6" id="login-form" action="#">
<div>
<label
for="email"
Expand Down Expand Up @@ -52,7 +60,16 @@ function LoginPage() {
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 "
required=""
/>
<span onClick={() => setPassVis(!passVis)} className="bg-red absolute right-4 top-10 text-gray-400 hover:cursor-pointer">{passVis ? <IoEyeOff className="h-5 w-5" /> : <IoEye className="h-5 w-5" />}</span>
<span
onClick={() => setPassVis(!passVis)}
className="bg-red absolute right-4 top-10 text-gray-400 hover:cursor-pointer"
>
{passVis ? (
<IoEyeOff className="h-5 w-5" />
) : (
<IoEye className="h-5 w-5" />
)}
</span>
</div>
<div class="flex items-center justify-between">
<div class="flex items-start">
Expand Down Expand Up @@ -80,7 +97,10 @@ function LoginPage() {
</div>
<button
type="submit"
class="w-full text-white bg-green-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center "
class="g-recaptcha w-full text-white bg-green-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center"
data-sitekey="6LfsY-8pAAAAAKOXCgEf_anUnVPrcOhW9pfIAVyX"
data-callback={onSubmit}
data-action='submit'
>
Sign in
</button>
Expand Down
37 changes: 33 additions & 4 deletions src/Pages/SignupPage.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { IoEye, IoEyeOff } from "react-icons/io5";
import { Helmet } from "react-helmet";

function SignupPage() {
const [passVis, setPassVis] = useState(false);
const [conVis, setConVis] = useState(false);

const onSubmit = (token) => {
document.getElementById("signup-form").submit();
};
return (
<>
<Helmet>
<script src="https://www.google.com/recaptcha/api.js" defer></script>
</Helmet>
<section class="bg-zinc-50 py-8 min-h-screen signup">
<div class="flex flex-col items-center max-w-[28rem] justify-center px-6 py-8 mx-auto mt-7 lg:py-8">
<a
Expand All @@ -21,7 +29,7 @@ function SignupPage() {
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl">
Create an account
</h1>
<form class="space-y-4 md:space-y-6" action="#">
<form class="space-y-4 md:space-y-6" id="signup-form" action="#">
<div>
<label
for="email"
Expand Down Expand Up @@ -53,7 +61,16 @@ function SignupPage() {
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5"
required=""
/>
<span onClick={() => setPassVis(!passVis)} className="bg-red absolute right-4 top-10 text-gray-400 hover:cursor-pointer">{passVis ? <IoEyeOff className="h-5 w-5" /> : <IoEye className="h-5 w-5" />}</span>
<span
onClick={() => setPassVis(!passVis)}
className="bg-red absolute right-4 top-10 text-gray-400 hover:cursor-pointer"
>
{passVis ? (
<IoEyeOff className="h-5 w-5" />
) : (
<IoEye className="h-5 w-5" />
)}
</span>
</div>
<div className="relative">
<label
Expand All @@ -70,7 +87,16 @@ function SignupPage() {
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5"
required=""
/>
<span onClick={() => setConVis(!conVis)} className="bg-red absolute right-4 top-10 text-gray-400 hover:cursor-pointer">{conVis ? <IoEyeOff className="h-5 w-5" /> : <IoEye className="h-5 w-5" />}</span>
<span
onClick={() => setConVis(!conVis)}
className="bg-red absolute right-4 top-10 text-gray-400 hover:cursor-pointer"
>
{conVis ? (
<IoEyeOff className="h-5 w-5" />
) : (
<IoEye className="h-5 w-5" />
)}
</span>
</div>
<div class="flex items-start">
<div class="flex items-center h-5">
Expand All @@ -96,7 +122,10 @@ function SignupPage() {
</div>
<button
type="submit"
class="w-full text-white bg-green-600 hover:bg-green-700 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center"
class="g-recaptcha w-full text-white bg-green-600 hover:bg-green-700 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center "
data-sitekey="6LfsY-8pAAAAAKOXCgEf_anUnVPrcOhW9pfIAVyX"
data-callback={onSubmit}
data-action="submit"
>
Create an account
</button>
Expand Down
4 changes: 4 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ body.dark .blog {
color: white;
}

.grecaptcha-badge {
bottom: 698px !important;
}

.close-animation{
overflow: hidden;
animation: close both 0.8s ;
Expand Down