Problem with redirect after FB.Connect.showPermissionDialog - javascript

I'm building a facebook connect app to publish content to user's streams. In order to do that, I need to get extended publish_stream permission from the users. I'm using the function code to do so.
Check connection status
<input type="button" onclick="statusSubmit('Permission to publish : ');" value="Check connection status" />
<script type="text/javascript">
function statusSubmit(status)
{
facebook_prompt_permission('publish_stream', function(accepted)
{
if(accepted) {
// User (already) has permission
alert(status + 'already granted');
}
else
{
// User does not have permission
alert(status + ' not granted');
}
});
}
function facebook_prompt_permission(permission, callbackFunc)
{
// Check if user has permission, if not invoke dialog.
FB.ensureInit(function() {
FB.Connect.requireSession(function(){
//check is user already granted for this permission or not
FB.Facebook.apiClient.users_hasAppPermission(permission,
function(result) {
// prompt offline permission
if (result == 0) {
// render the permission dialog
FB.Connect.showPermissionDialog(permission,
function(result){
if (null == result)
alert('no permissons granted');
else
alert('permissions ' + result);
}, true, null);
} else {
// permission already granted.
callbackFunc(true);
}
});
});
});
}
</script>
After the permissions dialog is displayed and the user grants the permissions, there is a redirect my current page on my local development machine. I cannot seem to control this redirect behaviour through my settings. I have tried changing the "Post-Authorize Callback URL" to a publicly visible page, but it does not get called. Is there something I'm missing? I would like to either
Get the post-authorize callback URL to something that works OR
Even better if there is no redirection after the user grants
permissions. This option would be the best.
Thank you for any suggestions.

abronte, Thank you for your suggestion. I actually figured out that the path to xd_receiver.htm was incorrect, which was causing all the weird behavior. When I corrected that, things were OK. But the FB Javascript API is very flaky, we decided not to use it as the behavior is erratic. We will be switching to a server based solution in the future.

I believe that the post-authorize callback url that is set in the application settings only deals with within facebook canvas sort of stuff. What url is called after you authorize the app in facebook.
What I think the best solution is (and this is what i do) is to manually redirect the user after the extended permissions prompt is completed.
window.location = '/path/to/something';

Related

Storing DeviceOrientationEvent and DeviceMotionEvent permissions across pages

I've got a nice DeviceMotionEvent request all working for Safari (or other browsers that require the permission), something along these lines:
// on click of a button
DeviceMotionEvent.requestPermission()
.then(response => {
if (response == 'granted') {
// do my thing
}
})
.catch(function(error) {
console.log(error);
// do my other thing
});
And thats working great. But when a user goes to a new page, they have to request the permission again. Obviously I'm calling 'requestPermission' again, so of course they would do.
How do I find out if permission has already been granted? Or is permission granted on a page by page basis (rather than session / site basis)?
I could store the response in localstorage or something, but would prefer something along the lines of:
DeviceMotionEvent.permissionStatus
Or something?
I think you only option is to build a single page application and use the history.pushState() to update the location in the browser, when you wish to ‘change pages’.
Edited:
You can use the Web Storage API with the following two mechanisms:
sessionStorage
localStorage
As the names imply, these two interfaces are ideal for session-based data or if you want to persist state even after the connection is closed.
You should be able to check whether permissions have been granted using the devicemotion eventListener. Baring in mind you have to push a button or similar to run DeviceMotionEvent.requestPermission()
eg.
let hasOrientationControls = false;
window.addEventListener("devicemotion", () => {
hasOrientationControls = true;
});
// then when the button is pressed we can request permissions if we need
onButtonPressed () => {
if (hasOrientationControls) return;
else DeviceMotionEvent.requestPermission();
}
I've also used this
isVRReady = window.DeviceOrientationEvent && "ontouchstart" in window;

Google OAuth disconnect, signOut but GoogleAuth.isSignedIn.get() = true?

Here is my code:
function googleLogOut() {
debugAlert("googleLogOut:Begin");
GoogleAuth.disconnect();
GoogleAuth.signOut().then(function () {
debugAlert("googleLogOut:Logout Completed, current login status = " + GoogleAuth.isSignedIn.get());
userNotLoggedIn();
debugAlert("googleLogOut:Exit");
});
}
According to my understanding, the disconnect revokes the authorization which the currently signed-in user has granted to my application and the signOut should log the user out of his Google account, basically backing out the OAuth signin which the user went through originally in order to gain access to my application.
However, immediately after GoogleAuth.signOut(), GoogleAuth.isSignedIn.get() evaluates to true - see alert dialog image:
Alert Dialog
Actually, as it turns out, the user is still logged in to his Google account so technically isSignedIn.get() is returning the correct value. I confirmed this by opening a new browser tab and going to gmail - clearly I was still logged in. More to the point though, what this code does is revoke all of the permissions which the user has granted to my application - that is the essence of this logout function. To test this -
GoogleAuth.currentUser.get().hasGrantedScopes(SCOPE) == false
So the compound test for whether a Google account is logged in to my application is:
GoogleAuth.isSignedIn.get() == true && GoogleAuth.currentUser.get().hasGrantedScopes(SCOPE) == true
Here's the modified logout function. (Same functionality, just modified the debug statements to show the revocation of the scopes privileges.)
function googleLogOut() {
debugAlert("googleLogOut:Begin");
GoogleAuth.disconnect();
GoogleAuth.signOut().then(function () {
debugAlert("googleLogOut:Logout Completed, current login status = " + GoogleAuth.isSignedIn.get());
if (GoogleAuth.isSignedIn.get()) {
debugAlert("googleLogOut:Logout Completed, current SCOPE status = " + GoogleAuth.currentUser.get().hasGrantedScopes(SCOPE));
}
userNotLoggedIn();
debugAlert("googleLogOut:Exit");
});
}
Here's a completely different way to do this. I found this to be much more reliable.
logoutWindow = window.open("https://accounts.google.com/SignOutOptions", "_blank", "toolbar=no,width=600,height=400");
I just open a window to Google's account management page. When the user signs out, they are signed out from my application as well.
As the icing on the cake, when I trap the user logged out event in my application I close the window - if the user is logging out through a window which my application has invoked:
try {
logoutWindow.close();
}
catch (err) {
// nothing...
}
Use GoogleAuth.isSignedIn.listen(listener) - when your listener is called the state of GoogleAuth objects has already been updated.

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.

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.

Google+ login via Sign In button: Trouble with persisting session across different pages, and displaying Login/Logout buttons

My page /login.php displays the signin button and signs you in. So far I have managed to:
Include relevant code in common files so that G+ signin code is present in all pages
Moved stuff from the button element itself to tags in the header
Instead of keeping any significant logic in my signinCallback, I attached a callback function that is called on each page load, like this:
po.src = 'https://apis.google.com/js/client:plusone.js?onload=OnLoadCallback';
I then made that function look like this:
function OnLoadCallback(){
var sessionParams = {
'client_id': 'myapp-id-here',
'session_state': null
}
gapi.auth.checkSessionState(sessionParams, function(stateMatched){
if(stateMatched === true){
console.log("You do not seem to be logged in!");
}else{
console.log("You should be logged in!");
// Trigger request to get the email address.
gapi.client.load('plus','v1', loadProfile);
if(window.location.pathname === '/login.php'){
toggleElement('signin-button');
window.location = "/";
}
}
});
}
I found this bit of code regarding the session state in some article but I'm not sure it works as it's supposed to. In Chrome it seems more or less OK but in FF, when I first tried it, it should give me "not logged" in my console. Since I was logged in FF with my google account (but not in my app!), it seemed to recognize me as logged in, or at least my session was anything but the null (as stated in the code).
So, what should I use instead of "null" when it comes to determining session state?

Categories

Resources