Created
June 27, 2025 08:33
-
-
Save siexp/1d82d1ed5b12cf16371b2e3542a26c38 to your computer and use it in GitHub Desktop.
google captcha example
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
// Frontend | |
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
import './index.css'; | |
import App from './App'; | |
import reportWebVitals from './reportWebVitals'; | |
import { LoginProvider} from './pages/LoginContext'; | |
import { WalletProvider} from './pages/WalletContext'; | |
import { RecaptchaProvider } from './pages/RecaptchaProvider' | |
ReactDOM.render( | |
<React.StrictMode> | |
<LoginProvider> | |
<WalletProvider> | |
// apply captcha on as POST request interceptor | |
<RecaptchaProvider> | |
<App /> | |
</RecaptchaProvider> | |
</WalletProvider> | |
</LoginProvider> | |
</React.StrictMode>, | |
document.getElementById('root') | |
); | |
// If you want to start measuring performance in your app, pass a function | |
// to log results (for example: reportWebVitals(console.log)) | |
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals | |
reportWebVitals(); |
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
// Backend | |
import { Middleware } from "@loopback/rest"; | |
const fetch = require("isomorphic-fetch"); | |
export const reCaptchaV3: Middleware = async (middlewareCtx, next) => { | |
const { request, response } = middlewareCtx; | |
try { | |
if (request.method === "POST" || request.method === "PUT") { | |
const token = request.header("X-Recaptcha"); | |
if (token === undefined || token === "") { | |
response.status(400).send({ | |
statusCode: 400, | |
name: "Error", | |
message: "reCaptcha header is not provided", | |
}); | |
} | |
// todo to env | |
const secret_key = "secret_key"; | |
const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${token}`; | |
const checkToken = async (req: any, res: any) => { | |
const body = await fetch(url, { | |
method: "post", | |
}); | |
const googleResp = await body.json(); | |
if (!googleResp.success) { | |
res.status(400).send({ | |
statusCode: 400, | |
name: "Error", | |
message: | |
"errors in reCaptcha check: " + | |
googleResp["error-codes"].join(","), | |
}); | |
} | |
}; | |
await checkToken(request, response); | |
} | |
const result = await next(); | |
return result; | |
} catch (err) { | |
// Catch errors from downstream middleware | |
console.log( | |
"Error received for %s %s", | |
request.method, | |
request.originalUrl | |
); | |
throw err; | |
} | |
}; |
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
// Frontend | |
import { useGoogleReCaptcha } from 'react-google-recaptcha-v3'; | |
import { useEffect } from 'react'; | |
export const Recaptcha = () => { | |
const { executeRecaptcha } = useGoogleReCaptcha(); | |
const { fetch: originalFetch } = window; | |
const handleReCaptchaVerify = async () => { | |
try { | |
if (!executeRecaptcha) { | |
throw new Error('Execute recaptcha not yet available'); | |
} | |
const token = await executeRecaptcha('login'); | |
if (!token) { | |
throw new Error('Recaptcha token is empty'); | |
} | |
localStorage.setItem('recaptchaToken', token); | |
return token; | |
} catch (error) { | |
console.error('Recaptcha verification failed:', error.message); | |
return null; | |
} | |
}; | |
const interceptFetch = async (resource, options) => { | |
const isPostRequest = options?.method?.toLowerCase() === 'post' || | |
options?.method?.toLowerCase() === 'put'; | |
if (isPostRequest) { | |
const token = await handleReCaptchaVerify(); | |
if (token) { | |
options = { | |
...options, | |
headers: { | |
...options?.headers, | |
'X-Recaptcha': token, | |
} | |
}; | |
} | |
} | |
return originalFetch(resource, options); | |
}; | |
useEffect(() => { | |
window.fetch = async (...args) => { | |
const [resource, options] = args; | |
return interceptFetch(resource, options); | |
}; | |
return () => { | |
window.fetch = originalFetch; | |
}; | |
}, [executeRecaptcha]); | |
return null; | |
}; |
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
// Frontend | |
import { GoogleReCaptchaProvider } from 'react-google-recaptcha-v3'; | |
export const RecaptchaProvider= props =>{ | |
return( | |
<GoogleReCaptchaProvider | |
reCaptchaKey="reCaptchaKey" | |
scriptProps={{ | |
appendTo: 'head', // optional, default to "head", can be "head" or "body", | |
}} | |
> | |
{props.children} | |
</GoogleReCaptchaProvider> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment