Close popup window for Google OAuth2 - javascript

I have my oauth2 for Gmail open up in a popup using newWindow = window.open(...) and then when the user is done filling it out and hit 'allow' it redirects to my server where the tokens are retrieved and stored. Finally, the server returns 'Error' or 'Success' so the popup will just have that in it. Now on the Angular side I have this running.
checkConnect = setInterval(function() {
try{
if(newWindow.document.body.innerText === 'Success') {
console.log('Success');
newWindow.close();
window.clearInterval(checkConnect);
}else if(newWindow.document.body.innerText === 'Error') {
console.log('We had an error!');
newWindow.close();
window.clearInterval(checkConnect);
}else if(newWindow.closed) {
console.log('WINDOW WAS closed');
window.clearInterval(checkConnect);
}
}catch(e) {
//console.log(e);
}
}, 100);
This works sometimes and other times it fails. I also reuse this code for other Oauth providers, such as Dropbox.Sometimes it works and sometimes it doesn't. Any idea why?

Well I couldn't figure it out by using a popup. However, I was able to over come this problem by just having the oauth page open in the same page and redirect back to the page I wanted the user on afterwards.
Also, there are libraries provided by google that open it for you in a popup and handle the closing.

Related

Why browser refresh and close event detection is not working for IE and Safari

I need to call logout function on the close of browser window gets close. It's working fine in Chrome not working in IE and Safari.
I have tried the following code:
window.onbeforeunload = function (e) {
// Your logic to prepare for 'Stay on this Page' goes here
var evtobj = window.event ? event : e;
if (evtobj == e) {
//firefox
if (!evtobj.clientY) {
//server call
}
}
else {
//IE
if (evtobj.clientY < 0) {
//server call
}
}
//return "Please click 'Stay on this Page' and we will give you candy";
};
I have tried a few other ways but they didn't work. Please advise.
There is something wrong in your design, you SHOULDN'T rely on a client-side hook to perform logout. There are one billion of reasons why that event could not be executed. Just limit the onbeforeunload event to execute informational content and not critical actions.
By the way:
Don't return in your beforeunload event! This creates some issue in IE
Use window.sessionStorage to make some data last until the user closes the tab
Use session cookies to store your user's sensitive data like as tokens, and check if a user is logged on the server, and not on the client

How to determine if google auth2.signIn() window was closed by the user?

Im implementing auth using this and am currently showing a loading icon in React when a user clicks the button to sign in and the auth2 account selection/login window shows.
However if a user closes the window, there doesnt seem to be any event fired i.e the signIn() function which returns a promise never resolves, I would have thought google would return an error for this promise if the window is closed. As a result there is no way for me to stop showing the loader icon and reshow the login menu.
I was wondering if anyone had a solution for this?
I try to modifiy my code that call Google OAuth 2.0 window.
You only have to add extra AJAX method that cover what is Google OAuth error result.
gapi.auth2.getAuthInstance().signIn()
Change it to this one,
gapi.auth2.getAuthInstance().signIn().then(function(response){
//If Google OAuth 2 works fine
console.log(response);
}, function(error){
//If Google OAuth 2 occured error
console.log(error);
if(error.error === 'popup_closed_by_user'){
alert('Oh Dude, Why you close authentication user window...!');
}
});
That's it...
For more detail about Google OAuth 2.0 information, you can visit this link.
https://developers.google.com/api-client-library/javascript/samples/samples#authorizing-and-making-authorized-requests
Sample code on JavaScript:
https://github.com/google/google-api-javascript-client/blob/master/samples/authSample.html
Although the API provides a mechanism for detecting when the user clicks the Deny button, there is not a built-in way for detecting that the user abruptly closed the popup window (or exited their web browser, shut down their computer, and so on). The Deny condition is provided in case you want to re-prompt the user with reduced scopes (e.g. you requested "email" but only need profile and will let the user proceed without giving you their email).
If the response from the sign-in callback contains the error, access_denied, it indicates the user clicked the deny button:
function onSignInCallback(authResult) {
if (authResult['error'] && authResult['error'] == 'access_denied') {
// User explicitly denied this application's requested scopes
}
}
You should be able to implement sign-in without detecting whether the window was closed; this is demonstrated in virtually all of the Google+ sample apps. In short, you should avoid using a spinner as you're doing and instead should hide authenticated UI until the user has successfully signed in.
It's not recommended you do this, but to implement detection of the pop-up closing, you could do something like override the global window.open call, then detect in window.unload or poll whether the window was closed without the user authenticating:
var lastOpenedWindow = undefined;
window.open = function (open) {
return function (url, name, features) {
// set name if missing here
name = name || "default_window_name";
lastOpenedWindow = open.call(window, url, name, features);
return lastOpenedWindow;
};
}(window.open);
var intervalHandle = undefined;
function detectClose() {
intervalHandle = setInterval(function(){
if (lastOpenedWindow && lastOpenedWindow.closed) {
// TODO: check user was !authenticated
console.log("Why did the window close without auth?");
window.clearInterval(intervalHandle);
}
}, 500);
}
Note that as I've implemented it, this mechanism is unreliable and subject to race conditions.

Manual page refresh required to show user's name as logged in

I have a website running on Apache/2.4.7 (Ubuntu) server without any errors, I installed on it a PHP script that use CodeIgniter 2.1.4 and Bootstrap.
At the top of the page, the login box works as modal popup but when someone attempts to sign in, the script reloads the page but doesn't show the user's name logged in. Only after a manual refresh of the page can the user see their name.
I've been trying to search for a solution for more than a month, including doing a new fresh install of both server and script, changing the .htaccess file, stopping memcached, etc.
I contacted both the owner of the script and CodeIgniter support, they told me that is probably an overload Ajax issue.
Since my script is mostly Ajax and it works fine except the login, is it possible to do the login in a different way? How could I integrate the script properly?
This is my login function (assets/js/custom.js):
function login() {
var email = $('#loginForm [name="email"]').val();
var pwd1 = $('#loginForm [name="password1"]').val();
if (isEmpty(pwd1) || isEmpty(email)) {
alert(msg_required_fields);
return false;
}
$.post(base_url + 'main/login', { "email": email, "pwd1": pwd1 }, function(data, textStatus, xhr) {
if (data.error == 1) {
alert(data.msg);
}
if (data.error == 0) {
document.location = base_url + 'main/reload';
}
}, "json");
}
UPDATE
I have the same problem also for the logout function:
function logout()
{
$this->admin->deleteTable('online',array('iduser' => $this->session->userdata('id')));
$this->session->unset_userdata('id');
$this->session->sess_destroy();
if( $this->session->userdata('facebook') == '1')
redirect(base_url(),"main/facebook/logout");
else
redirect(base_url()."main/reload","refresh");
}
logically the document.location object should be read-only (as you can't change the URL of a document; changing the URL loads a new document), so to be on the safe side you should rather use window.location.href when you want to set the URL.
so you should try with window.location.href
What is the difference between document.location.href and document.location?

Does Notification HTML5 work in local in Chrome?

I am trying to create a notification in Chrome.
I have write this simple code but there is notification shown in CHrome whereas checkPermission() return well 0.
I do the same thing than this website (example), which works fine in my Chrome browser.
if (window.webkitNotifications.checkPermission() == 0) {
window.webkitNotifications.createNotification("icon.png", "title", "text").show();
} else {
window.webkitNotifications.requestPermission();
}
Where is the problem ?
[EDIT : Problem fixed]
In fact, i allows to show notification from all website in Chrome settings, and now, it works fine !
Request permission only work on a user gesture (see below question, and quote from the docs).
In short you need to register a click event or something similar then request permission.
document.querySelector('#show_button').addEventListener('click', function() {
if (window.webkitNotifications.checkPermission() == 0) { // 0 is PERMISSION_ALLOWED
var notification = window.webkitNotifications.createNotification(
'icon.png', 'Notification Title', 'Notification content...');
notification.show();
} else {
window.webkitNotifications.requestPermission();
}
}, false);
Here's a jsfiddle
Webkit notifications requestPermission function doesn't work
requestPermission Requests that the user agent ask the user for
permission to show notifications from scripts. This method should only
be called while handling a user gesture; in other circumstances it
will have no effect. This method is asynchronous. The function
provided in callback will be invoked when the user has responded to
the permission request. If the current permission level is
PERMISSION_DENIED, the user agent may take no action in response to
requestPermission.

fb login popup block

I am making using fb login feature but problem comming to me is that whenever I click on the fb login button before page media loading is completed, it blocks the popup for fb login but if I click on fblogin after a second passed to loading event it works
Here is the function I am using:
function fb_login() {
var email='';
console.log(loginClassbackQueue);
// console.log('user wants to login with fb');
FB.getLoginStatus(function(response) {
if(response.status!='connected'){
FB.login(function(response) {
// console.log(response);
if (response.authResponse) {
// console.log('user logged in successfully');
// console.log(response);
email = update_f_data_login(response);
$('#fb_login_popup, #popup_overlay').hide();
// loginme(email);
}
else {
loginClassbackQueue = [];
// console.log('user failed to login');
}
// console.log('fb login completed successfully');
}, {scope:"email,user_birthday,user_likes,user_location,friends_likes,publish_actions"}
);
}
else{
// console.log('logged in and connected');
email = update_f_data_login(response);
$('#fb_login_popup, #popup_overlay').hide();
}
});
}
The same action when I do on this site http://fab.com/ it open popups always never block a popup.
You cannot call FB.login from the callback of FB.getLoginStatus.
Browsers tend to block popup windows of the popup is not spawned as an immediate result of a user's click action.
Because FB.getLoginStatus does an ajax call and you call FB.login on it's response, the popup that would open as a result of this call is blocked.
A solution to your problem would be to call FB.getLoginStatus on page load and use the response inside your fb_login() method.
It's perfectly fine to call FB.login from the callback of FB.getLoginStatus, as long as you are confident that the login status has already been loaded internally. To do this, use one of these:
FB.init({..., status: true, ... }).
FB.getLoginStatus(...)
FB.login(...)
FB.ui(...)
Technically all of these options use FB.ui. The async process has to complete, which could take a few seconds. As long as you have already used one of the methods above to make a cross-domain call with FB, and that async process has completed, getting the login status will not make an async call, and the popup will not be blocked.
You should also make sure not to specify true for the second parameter, as in FB.getLoginStatus(..., true);.
Make sure you set status to true, this will fixed popup blocker issue.
window.fbAsyncInit = function() {
FB.init({
appId : '{your-app-id}',
cookie : true, // enable cookies to allow the server to access
// the session
xfbml : true, // parse social plugins on this page
version : 'v2.5', // use graph api version 2.5
status : true // set this status to true, this will fixed popup blocker issue
});
I had the same problem and it kick my head for 3 days. I did stumble on the above mentioned solutions and they worked in Firefox and Edge but in Chrome not matter what ever i did i still got blocked left right and center.The other problem was when i called the function from a button press event the login dialog was not block but it didn't get any responses after the login dialog closes for further actions so i got stuck. So my solution is as follow, but you don't need to press the login in button it will redirect to the FB-login page without a button press event, and on return continue with all the other sdk steps. Just add this to your code and see if it helps, from there adjust according to your need
function statusChangeCallback(response) {
console.log('statusChangeCallback');
console.log(response);
// The response object is returned with a status field that lets the
// app know the current login status of the person.
// Full docs on the response object can be found in the documentation
// for FB.getLoginStatus().
if (response.status === 'connected') {
// Logged into your app and Facebook.
document.getElementById('Image2').style.display = "none";
document.getElementById('mail').style.display = "in-line";
testAPI();
} else {
// The person is not logged into your app or we are unable to tell.
window.alert("Faça login no facebook antes de continuar - Obrigado");
window.location.href = 'https://www.facebook.com/dialog/oauth' +
'?client_id=55215442252214521548' +
'&scope=public_profile,email,user_friends' +
'&redirect_uri=' + encodeURIComponent(document.URL);
document.getElementById('Image2').style.visibility = "hidden";
document.getElementById('mail').style.display = "in-line";
}
}
// This function is called when someone finishes with the Login
// Button. See the onlogin handler attached to it in the sample
// code below.
function checkLoginState() {
FB.getLoginStatus(function (response) {
statusChangeCallback(response);
});
}

Categories

Resources