-
Notifications
You must be signed in to change notification settings - Fork 955
Closed
Labels
Description
[REQUIRED] Describe your environment
- Operating System version: MacOS Monterey 12.3
- Browser version: Chrome version 100.0.4896.75
- Firebase SDK version: 9.6.10
- Firebase Product: auth
[REQUIRED] Describe the problem
When I use the RecaptchaVerifier on my site with AppCheck enabled, I get an error when I call the verify method on the RecaptchaVerifier. The error is as follows:
TypeError: this.getAssertedRecaptcha(...).render is not a function
This only happens when AppCheck is enabled; without AppCheck it behaves normally, that is, the verification goes through. Also, it doesn't happen in development or production when running at localhost with the emulator. Only occurs in the deployed code in firebase hosting.
Steps to reproduce:
- Create a react app with firebase app check enabled
- Create a simple page with an invisible RecaptchaVerifier and a button that when clicked calls 'RecaptchaVerifier.verify()'
- Build the app and deploy to hosting
- Notice the error occurs when you press the button that calls the verify function
Relevant Code:
In my root App.tsx file, appcheck is initialized this way
if(!getApps().length){
const app = initializeApp(firebaseConfig)
// console.log(`Initializing app check with ${import.meta.env.VITE_RECAPTCHA_KEY}`)
//if localhost set debug app check token
//https://firebase.google.com/docs/app-check/web/debug-provider?authuser=0&hl=en
if (window.location.hostname === "localhost"){
//this must be set to true to generate a new token and once generated and registered, we need to set the token value in env
//(self as any).FIREBASE_APPCHECK_DEBUG_TOKEN = true
(window.self as any).FIREBASE_APPCHECK_DEBUG_TOKEN = import.meta.env.VITE_APP_CHECK_DEBUG_TOKEN
}
initializeAppCheck(app, {
provider: new ReCaptchaEnterpriseProvider(import.meta.env.VITE_RECAPTCHA_KEY),
isTokenAutoRefreshEnabled: true
})
}
The RecaptchaVerifier component is as follows
export const FirebaseRecaptcha = ({instructionMessage, onVerificationComplete}: FirebaseRecaptchaProps)=>{
const [isCaptchaLoading, setCaptchaLoading] = useState(false)
const [verificationErrored, setVerificationErrored]= useState(false)
let verifier: any = null
useEffect(()=>{
console.log("Initializing captcha");
verifier = new RecaptchaVerifier("recaptcha-container", {
'size': 'invisible',
'callback': function(response: any) {
console.log("verification success")
setCaptchaLoading(false)
onVerificationComplete(CaptchaVerificationStatus.SUCCESS)
}
}, getAuth())
},[])
const onStartClick = async ()=> {
if(verifier){
try {
setCaptchaLoading(true)
console.log("About to verify")
const res = await verifier.verify()
}catch(e){
setCaptchaLoading(false)
console.error(e)
onVerificationComplete(CaptchaVerificationStatus.FAIL)
}
}
}
// <Button variant="contained" color="primary" id={recaptchaButtonId} onClick={()=>onStartClick()} className={`${classes.actionButton} ${classes.bottomMargin}`}>
// Start
// </Button>
return (
<>
<div id="recaptcha-container"></div>
<Typography variant="h6" gutterBottom sx={{mb: 2}}>
{instructionMessage ? instructionMessage : getStrings().message_start_page}
</Typography>
{isCaptchaLoading ?
<CircularProgress sx={{mb: 2}} /> :
<Button variant="contained" color="primary" onClick={()=>onStartClick()} sx={{mb: 2, width: '50%'}}>
{getStrings().button_start}
</Button>
}
</>
)
}
DMZakaria and clive-h-townsend