Im trying to implement 3d secure, I have html code and I can open it in iframe as srcDoc (html string).And I want to access the form inside the iframe by using useref and close the iframe if form is posted.But I always got this error "react-dom.development.js:20724 Uncaught DOMException: Failed to read a named property ‘document’ from ‘Window’: Blocked a frame with origin "http://localhost:3000" from accessing a cross-origin frame." (by the way ,I enable cross origin in config ,and try –disable-web-security in chrome but still same error…
Any help is appricated,thx.
const ref = useRef();
// this is html document ,base64
const bss="PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CiAgICA8dGl0bGU+aXl6aWNvIE1vY2sgM0QtU2VjdXJlIFByb2Nlc3NpbmcgUGFnZTwvdGl0bGU+CjwvaGVhZD4KPGJvZHk+Cjxmb3JtIGlkPSJpeXppY28tM2RzLWZvcm0iIGFjdGlvbj0iaHR0cHM6Ly9zYW5kYm94LWFwaS5peXppcGF5LmNvbS9wYXltZW50L21vY2svaW5pdDNkcyIgbWV0aG9kPSJwb3N0Ij4KICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im9yZGVySWQiIHZhbHVlPSJtb2NrNDYtNjg3NjU1ODAwODI2MjM5NWl5emlvcmQiPgogICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iYmluIiB2YWx1ZT0iNTUyNjA4Ij4KICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InN1Y2Nlc3NVcmwiIHZhbHVlPSJodHRwczovL3NhbmRib3gtYXBpLml5emlwYXkuY29tL3BheW1lbnQvaXl6aXBvcy9jYWxsYmFjazNkcy9zdWNjZXNzLzI3Ij4KICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImZhaWx1cmVVcmwiIHZhbHVlPSJodHRwczovL3NhbmRib3gtYXBpLml5emlwYXkuY29tL3BheW1lbnQvaXl6aXBvcy9jYWxsYmFjazNkcy9mYWlsdXJlLzI3Ij4KICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImNvbmZpcm1hdGlvblVybCIgdmFsdWU9Imh0dHBzOi8vc2FuZGJveC1hcGkuaXl6aXBheS5jb20vcGF5bWVudC9tb2NrL2NvbmZpcm0zZHMiPgogICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iUGFSZXEiIHZhbHVlPSJjYWIxNjA0YS02MWJiLTQ0NGQtOGExNS1kZDZmMzhjZGRiNjMiPgo8L2Zvcm0+CjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4KICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJpeXppY28tM2RzLWZvcm0iKS5zdWJtaXQoKTsKPC9zY3JpcHQ+CjwvYm9keT4KPC9odG1sPg=";
const [htmlbase, setHtmlbase] = useState('');
useEffect(() => {
setHtmlbase(decode(bss2));
}, []);
const buttonOnclick = () => {
// this attempts always null ,cant access the document in iframe
const frame = ref.current;
if (frame.current?.contentDocument) // FF Chrome
ifrDoc = frame.current?.contentDocument;
else if ( frame.current?.contentWindow ) // IE
ifrDoc = frame.current?.contentWindow.document;
};
<iframe
width="500px" id="myIframe"
height="320px"
srcDoc={htmlbase}
sandbox="allow-forms allow-modals allow-same-origin allow-scripts allow-popups allow-top-navigation"
onLoad={handleFrameElement}
position="relative" ref={ref}/>
3
Answers
As you know, that Next.JS is a modern web framework which can work in both server and client side. To access the iframe and window make sure that your page is run on client side not in server side. Because the default Next.JS 14 AppRouter is run on server side, not in client side.
In the top of your page add
'use client'
to make sure that you’re using client-side rendering.But if you want to access it inside server side rendering, make sure that window is exist before attempting any DOM manipulation. For example
That error message means you don’t currently have access to the content of the iframe. This can happen because either it has not actually loaded yet, or because the browser sees it coming from a different domain to the parent page.
Decoding your base64 string gives.
This is redirecting to another site (I’m guessing
sandbox-api
isn’t the site of the main app), so once the form is submitted, the iframe is then cross domain and I am guessing you don’t want to close it before it has submitted.The best you can do, if you don’t want to change the three response URLs to you own site, is wait for the
onLoad
event to fire a second time on the iframe. This will indicate that the form has completed submission and the response page has loaded.If for some reason that is the same domain as the parent, then my next suggestions would be to remove
sandbox
and then not usesrcdoc
, as it creates it’s own set of issues in my experience.After writing the other answer, I noticed your
buttonOnclick
function.Your referencing
current
twice, shouldn’t this just beYou don’t need the rest of this code,
contentDocument
goes back to IE8.