Easy window OAUTH (frontend)

Search for a command to run...

No comments yet. Be the first to comment.
~10× less output, ~3× faster, measured. Plus the second lever — history compaction — that cuts multi-turn input ~60%.

And to improve your code

So I made a cheat sheet in plain english

A step-by-step guide

Today we deploy a website on our own server

TL;DR Use localStorage to communicate between windows and check it when the window is closed.
The OAUTH e2e process is as follows:
Back End(BE): on that route you do the following:
check if everything was ok with the authorization of your app in the social network provider,
take the returned token, email, username and whatever else you need
query your database which usually gives you two options:
redirect the user to a page in your app(homepage) with the state changed to logged in
Whenever you do an OAUTH login, you will need to setup 2 routes:
Example in adonisjs:
// route 1 - the redirect from your app to google
Route.get('/google/redirect', async (ctx) => {
const { default: GoogleController } = await import(
'App/Controllers/Http/GoogleController'
)
return new GoogleController().redirect(ctx);
}).middleware('guest');
// route 2 - the callback from google to your app
Route.get('/google/callback', async (ctx) => {
const { default: GoogleController } = await import(
'App/Controllers/Http/GoogleController'
)
return new GoogleController().callback(ctx);
}).middleware('guest');
However, a difficulty might appear if you decide to open 'route 1' in another window, as the callback will be returned in the same popup window and your user will be logged in in that window. And I hope we can agree that this is not a good UI.
You will need a third route, that will have the only purpose to render a blank page with some JavaScript code that will do the following:
set an item in the localStorage
close that window
You will redirect your app to this third route from the controller that handles route 2 after everything was fine and you've logged in the user.
// route 3 - the login success redirect
Route.get('/social-success-redirect', async ({ view }) => {
return view.render('auth/social-success-redirect')
})
The social-success-redirect template will basically be a blank html page with a script similar to this. Note this is a simplified version.
localStorage.setItem('socialLogin', true);
// you are in a window popup that you need to close
window.open(location, '_self').close();
And in the login page, you will have something like this:
const socialLoginBtn = document.getElementById('social-login');
const socialLoginStorageKey = 'socialLogin';
if (socialLoginBtn) {
socialLoginBtn.addEventListener('click', socialLogin)
}
async function socialLogin(event) {
event.preventDefault();
// wait for the window to get closed
const response = await socialLoginPromise();
// if it's closed by the user without the actual login, show an error
if (!response) {
return showSocialLoginError();
}
// if everything is okay, you redirect to the homepage and clear the storage key
window.location.href = '/';
clearLocalStorageKey(socialLoginStorageKey);
}
function socialLoginPromise() {
return new Promise(resolve => {
openPopupWindow('http://localhost:3333/google/redirect', resolve);
})
}
function openPopupWindow(url, promiseResolver) {
const windowFeatures = "height=600,width=600";
const newWindow = window.open(url, 'socialLogin', windowFeatures);
// important step: in an interval you check if the window is closed
// when it's closed, you resolve the promise with the local storage data
const intervalWindowCheck = setInterval(() => {
if (newWindow.closed) {
clearInterval(intervalWindowCheck);
// you get the key that should be set up in the window
const storageLoginStatus= window.localStorage.getItem(socialLoginStorageKey)
resolve(storageLoginStatus);
}
}, 1000);
if (window.focus) {
newWindow.focus()
}
}
Don't forget to do error handling.
Cheers!