I am bulding a web app: a SPA using React in frontend and Django rest framework to API endpoints.
I am in the part of the social login, which is done entirely in the backend (there is a exchange of providers tokens by own JWTs), so it is necessary make the request to the server, which redirect the user to the login of the specific provider. However, due to Facebook, Google and others providers do not permit this request using AJAX, I decided to create a popup (through window.open()
) to make this redirection.
Whether login is successful this window is redirect again towards a View of Django that returns a JSON with the JWT. Hence, this secondary window has a JWT in the domain of my server (Django).
I planned read this JSON from the body of this secondary window to get the JWT, and I read (Code response form parent window, SecurityError: Blocked... and others) the only way to communicate windows in different domains is with postMessage()
. But when I try, I receive the next message:
SecurityError: Permission denied to access property "document" on cross-origin object
In fact both of them are runnning in localhost, just with different port. That's the reason why is activate the same-origin policy.
Example of my button to open the window of social network login.
<button
className="facebookI"
title="Facebook"
type="button"
onClick={loginSocial}
>
<i className="fab fa-facebook-f" title="Facebook"></i>
</button>
The functions that manage the click and made the read attempt.
const loginSocial = ({target}) => {
let socialWindow = null;
socialNetwork = target.title.toLowerCase();
request = `/kuku_api/social-auth/login/${socialNetwork}/`;
if(socialWindow === null || socialWindow.closed) // If there is no window open
socialWindow = openWindow(request, width, height, x, y);
main = socialWindow.opener;
// I coded a setTimeout to made the next after the login
main.postMessage(socialWindow?.document?.body, 'http://local.react:3000');
}
const openWindow = (request, width, height, x, y) => {
return window.open(
'http://local.django:8000' + request,
'SocialLogin',
'popup,location,width=' + width + ',height=' + width + ',left=' + x + ',top=' + y + ''
);
}
And the listener of the 'message'.
useEffect(() =>{
window.addEventListener('message', handleMessage);
return () => ( window.removeEventListener('message', handleMessage) );
}, []);
const handleMessage = (e) => {
if(e.origin !== 'http://local.react:3000'){
return;
}
console.log(`Test ${e?.origin}`);
console.log(`Test ${e?.source}`);
console.log(`Test ${e?.data}`);
};
Where is my mistake? Or, there is any way to could read this JWT of the body of the secondary window?
Maybe, I have taken a wrong approach. Please feel free of make suggestions about how achieve this in a better way.