gapi.auth.signOut(); not working I'm lost - oauth

Below is the code I am using to login with google. I have an element on login.php with id authorize-button. When clicked it logs in just fine.
I have a logout link in my header file. When I click the logout it calls gapi.auth.signOut(); then it destroys session and redirects back to login.php
This happens as far as I can tell but then it just logs the user right back into our site with google. This is a pain as some of our users switch from google to facebook logins.
Thanks in advance for any help.
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
window.setTimeout(checkAuth, 1);
}
function checkAuth() {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
}
function handleAuthResult(authResult) {
var authorizeButton = document.getElementById('authorize-button');
if (authResult && !authResult.error) {
//authorizeButton.style.visibility = 'hidden';
makeApiCall();
} else {
//authorizeButton.style.visibility = '';
authorizeButton.onclick = handleAuthClick;
}
}
function handleAuthClick(event) {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
return false;
}
function signOut() {
gapi.auth.signOut();
}
function makeApiCall() {
gapi.client.load('oauth2', 'v2', function() {
var request = gapi.client.oauth2.userinfo.get();
request.execute(function(logResponse) {
var myJSON = {
"myFirstName": logResponse.given_name,
"myLastName": logResponse.family_name,
"name": logResponse.name,
"socialEmailAddress": logResponse.email
};
gapi.client.load('plus', 'v1', function() {
var request = gapi.client.plus.people.get({
'userId': 'me'
});
request.execute(function(logResponse2) {
//alert(JSON.stringify(logResponse));
myJSON['profilePicture'] = logResponse2.image.url;
myJSON['socialId'] = logResponse2.id;
//alert(JSON.stringify(myJSON));
$.ajax({
type: "POST",
url: "includes/login-ajax.php",
data: "function=googleLogin&data=" + JSON.stringify(myJSON),
dataType: "html",
success: function(msg) {
if (msg == 1) {
//window.location = "settings.php";
}
}
});
});
});
});
});
}

Make sure you have set your cookie-policy to a value other than none in your sign-in button code. For example:
function handleAuthClick(event) {
gapi.auth.authorize(
{
client_id: clientId,
scope: scopes,
immediate: false,
cookie_policy: 'single_host_origin'
},
handleAuthResult);
return false;
}
Note that sign out will not work if you are running from localhost.

Weird issue, but solved my problem by rendering the signin button (hidden) even if the user is authenticated.
See full question/answer here https://stackoverflow.com/a/19356354/353985

I came across the same issue today. I have search for solution the whole. The only reliable solution that worked for me is through revoke as explained here
I stored access_token in session which is needed during revoke
Below is my code you may find it useful
function logout() {
var access_token = $('#<%=accessTok.ClientID %>').val();
var provider = $('#<%=provider.ClientID %>').val();
if (access_token && provider) {
if (provider == 'GPLUS') {
var revokeUrl = 'https://accounts.google.com/o/oauth2/revoke?token=' +
access_token;
// Perform an asynchronous GET request.
$.ajax({
type: 'GET',
url: revokeUrl,
async: false,
contentType: "application/json",
dataType: 'jsonp',
success: function (nullResponse) {
// Do something now that user is disconnected
// The response is always undefined.
},
error: function (e) {
// Handle the error
// console.log(e);
// You could point users to manually disconnect if unsuccessful
// https://plus.google.com/apps
}
});
}
else if (provider == 'FB') {
FB.getLoginStatus(function (response) {
if (response.status === 'connected') {
FB.logout();
}
});
}
} else {
}
}

Related

OAuth2 in electron application in current window

I'm trying to implement OAuth2 authentication in Angular 2 ( Electron ) application.
I achieve that on the way with a popup that is called after user click on 'Sign In' button.
In popup user types their credentials and allows the access and on confirm code is returned and I'm able to catch redirect request which I can't do without popup.
Here is implementation that works:
return Observable.create((observer: Observer<any>) => {
let authWindow = new electron.remote.BrowserWindow({ show: false, webPreferences: {
nodeIntegration: false
} });
authWindow.maximize();
const authUrl = AUTHORIZATION_WITH_PROOF_KEY_URL
+ `?client_id=${CLIENT_ID}&response_type=code&scope=api_search&`
+ `redirect_uri=${REDIRECT_URL}&code_challenge=${challenge}&code_challenge_method=S256`;
if (this.clearStorage) {
authWindow.webContents.session.clearStorageData({}, () => {
this.clearStorage = false;
authWindow.loadURL(authUrl);
authWindow.show();
});
} else {
authWindow.loadURL(authUrl);
authWindow.show();
}
authWindow.webContents.on('did-get-redirect-request', (event, oldUrl, newUrl) => {
const code = this.getCode(newUrl, authWindow);
if (!code) {
this.clearStorage = true;
return;
}
this.requestToken({
grant_type: 'authorization_code',
code: code,
code_verifier: verifier,
redirect_uri: REDIRECT_URL
})
.subscribe((response: { access_token: string, refresh_token: string }) => {
observer.next(response);
});
});
// Reset the authWindow on close
authWindow.on('close', () => {
authWindow = null;
});
});
and as you can see in above code I'm creating new BrowserWindow with:
new electron.remote.BrowserWindow({ show: false, webPreferences: {
nodeIntegration: false
} });
and with that approach I'm able to catch up redirect request with a block of code that starts with:
authWindow.webContents.on('did-get-redirect-request', (event, oldUrl, newUrl) => {
....
}
but I'm not able to solve this without popup ( modal ).
Here is my attempt:
return Observable.create((observer: Observer<any>) => {
let authWindow = electron.remote.getCurrentWindow();
const authUrl = AUTHORIZATION_WITH_PROOF_KEY_URL
+ `?client_id=${CLIENT_ID}&response_type=code&scope=api_search&`
+ `redirect_uri=${REDIRECT_URL}&code_challenge=${challenge}&code_challenge_method=S256`;
if (this.clearStorage) {
authWindow.webContents.session.clearStorageData({}, () => {
this.clearStorage = false;
authWindow.loadURL(authUrl);
});
} else {
authWindow.loadURL(authUrl);
}
authWindow.webContents.on('did-get-redirect-request', (event, oldUrl, newUrl) => {
debugger;
// this is not called, I'm not able to catch up redirect request
});
// Reset the authWindow on close
authWindow.on('close', () => {
authWindow = null;
});
});
With my approach I get login screen from remote URL in a current window, but the problem is that I'm not able to catch redirect request with ('did-get-redirect-request') event.
I also tried with 'will-navigate' and many others.
Although I don't have a direct answer I thought I'd point you to Google's AppAuth-JS libraries, which cover OAuth based usage for Electron Apps.
My company have used AppAuth libraries for the mobile case and they worked very well for us, so that we wrote less security code ourselves and avoided vulnerabilities.
There is also an Electron Code Sample.

Titaniuim: Facebook login event doesn't fire

I am trying to login through facebook.
I have all info in plist and in entitlelements file
So when I click to button it is redirecting safari facebook page and asking to confirm
When I click to OK it doesn’t fire ‘login’ event and it is not logged.
Currently I am testing on iOS 5s Simulator
Here is the code
var fbook = require('facebook');
fbook.appid = <MyAPP_ID>;
fbook.permissions = ['public_profile'];
//fbook.forceDialogAuth = true;
if (fbook.loggedIn) {
//progress.hide();
params = {
access_token : fbook.accessToken
};
fbook.requestWithGraphPath('/me', params, 'GET', function(e) {
var result = JSON.parse(e.result)
});
} else {
fbook.addEventListener('login', function(e) {
//alert('try to login');
if (e.success) {
//progress.hide();
params = {
access_token : fbook.accessToken
};
fbook.requestWithGraphPath('/me', params, 'GET', function(e) {
var result = JSON.parse(e.result);
Ti.API.info("Result is : " + e.result);
});
} else if (e.error) {
Ti.API.info("error");
//alert('Error: ' + e.error);
} else if (e.cancelled) {
Ti.API.info("cancelled");
}
});
fbook.authorize();
/*
fbook.addEventListener('logout', function(e) {
fbook.logout();
});*/
}

How to get updated session data on rails using AngularJs without page refresh

I'm currently working on integrating devise as an authentication backend with angular as its frontend.
I have faced a problem on when login and logout, the session data will be updated untill the page refresh.
What i will do get session data without page refresh..?
Thanks for your Answers...
AngularJs Controller :
function UsersCtrl($scope, Session) {"use strict";
$scope.CurrentUser = Session.requestCurrentUser();
$scope.login = function(user) {
$scope.authError = null;
Session.login(user.email, user.password)
.then(function(response) {
if (!response) {
$scope.authError = 'Credentials are not valid';
} else {
$scope.authError = 'Success!';
}
}, function(response) {
$scope.authError = 'Server offline, please try later';
});
};
$scope.logout = function() {
// alert("woow");
Session.logout();
};
$scope.register = function(user) {
$scope.authError = null;
console.log(user);
Session.register(user.email, user.password, user.confirm_password)
.then(function(response) {
}, function(response) {
var errors = '';
$.each(response.data.errors, function(index, value) {
errors += index.substr(0,1).toUpperCase()+index.substr(1) + ' ' + value + ''
});
$scope.authError = errors;
});
};
}
AngularJs Session Service:
angular.module('sessionService', ['ngResource'])
.factory('Session', function($location, $http, $q) {
// Redirect to the given url (defaults to '/')
function redirect(url) {
url = url || '/';
$location.path(url);
}
var service = {
login: function(email, password) {
return $http.post('/users/login', {user: {email: email, password: password} })
.then(function(response) {
service.currentUser = response.data.user;
if (service.isAuthenticated()) {
//$location.path(response.data.redirect);
$location.path('/store');
}
});
},
logout: function() {
$http.delete('/sessions').then(function(response) {
$http.defaults.headers.common['X-CSRF-Token'] = response.data.csrfToken;
service.currentUser = null;
redirect('/store');
});
},
register: function(email, password, confirm_password) {
return $http.post('/users', {user: {email: email, password: password, password_confirmation: confirm_password} })
.then(function(response) {
service.currentUser = response.data;
if (service.isAuthenticated()) {
console.log("authenticated");
$location.path('/');
}
});
},
requestCurrentUser: function() {
if (service.isAuthenticated()) {
return $q.when(service.currentUser);
} else {
return $http.get('/users').then(function(response) {
service.currentUser = response.data.user;
return service.currentUser;
});
}
},
currentUser: null,
isAuthenticated: function(){
return !!service.currentUser;
}
};
return service;
console.log(service);
});
One Thing about building applications like this (restful) is that understanding the the backend as an api and app as a front-end very well.
Then think about a story as such;
In the login screen of your app
Front-end: You Provided the credentials to your backend;
Back-end: Checked and authenticated then It will create a unique hash stored in db (JWT recommended to check expiration in frontend) to your Front-end.
Front-end:Save it in a cookie.
Also place it in your ajax setting header part as "Authorization: {token}"
Front-end: Then send each request with this header to your backend.
Back-end: Always check if the token is present and valid to provide resources.
http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/ this link has helped me understand the whole thing and misconceptions in the past.
use $window.location.reload(); before page redirect.
One way to achieve this could be overriding the devise sessions_controller destroy action and afrer doing sign_out #current_user return the session as json

Can't access OAuth2 Youtube API V3

i'm trying to view my channel video list and i got this error invalid_client.
The OAuth client was not found. that means client id is wrong!.
var OAUTH2_CLIENT_ID = '############';
var OAUTH2_SCOPES = ['https://www.googleapis.com/auth/youtube'];`
`googleApiClientReady = function () {
gapi.auth.init(function () {
window.setTimeout(checkAuth, 1);
});
}
function checkAuth() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: true
}, handleAuthResult);
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
$('.pre-auth').hide();
$('.post-auth').show();
loadAPIClientInterfaces();
} else {
$('#login-link').click(function () {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: false
}, handleAuthResult);
});
}
}
function loadAPIClientInterfaces() {
gapi.client.load('youtube', 'v3', function () {
handleAPILoaded();
});
}
A screenshot of the console.google :
You don't need to be connected or use Oauth2 to view the list of your videos with the YouTube API. You only need an api key.
A sample example :
function googleApiClientReady() {
var apiKey = 'YOUR_API_KEY';
gapi.client.setApiKey(apiKey);
gapi.client.load('youtube', 'v3', function() {
isLoad = true;
});
request = gapi.client.youtube.search.list({
part: id, snippet
type: 'video',
order: 'date'
});
request.execute(function(response) {
//list of all your video in the response
});
}
Don't forget to add this file to your index.html and add this following line after :
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
From doc YouTube API

JQuery UI Multiple Dialogs Not Working

I have a page with two links that open two different modals, the "forgotten password" link opens the "forgotten password" modal and the "tell-a-friend" link opens the "tell-a-friend" modal.
Both modals contain forms that can be submitted.
The problem is if I open the first modal and submit it or close it, I cannot submit the second modal.
I can open the second modal, but I cannot submit it.
Please advise what the problem could be!
Here below is the javascript code that resides in separate javascript file, which is then imported into the HTML file. It is not inline javascript, if that would matter.
[code]
var forgottenPasswordDiv;
var tellAFriendDiv;
function clearErrorMessages() {
$('#errorMessage').text("");
}
function openForgottenPassword() {
forgottenPasswordDiv = $('#forgotten-password');
$('#forgotten-password').load("/Templates/include/new/ajax/modal/forgottenPassword.jsp")
.dialog(
{
autoOpen:false,
modal:true,
position:'left+35% top+20%',
width:'330',
height:'auto'
}
);
$('#forgotten-password').dialog('open');
}
function closeForgottenPassword() {
forgottenPasswordDiv.dialog("close");
}
function submitForgottenPassword() {
clearErrorMessages();
var email = $('#email').val();
if (email == null || email == '') {
$('#errorMessage').text("Please enter your user name or email");
} else {
clearErrorMessages();
/* Ajax Post */
var formData = $("#forgottenPasswordForm").serialize();
$.ajax({
type: "GET",
url: "/Templates/include/new/ajax/forgottenPassword.jsp",
data: formData,
success: function(data) {
if (data.error != null) {
$("#errorMessage").text(data.error);
} else {
$('#forgottenPasswordForm , .info').fadeOut(1000);
$("#successMessage").text(data.success);
$("div").removeClass('display-none');
}
},
dataType: 'json'
});
}
}
function openTellAFriend(gunId) {
tellAFriendDiv = $('#tell-a-friend');
$('#tell-a-friend').load("/Templates/include/new/ajax/modal/tellAFriend.jsp?id=" + gunId)
.dialog(
{
autoOpen:false,
modal:true,
position:'center top+10%',
width:'330',
height:'auto'
}
);
$('#tell-a-friend').dialog('open');
}
function closeTellAFriend() {
tellAFriendDiv.dialog("close");
}
function submitTellAFriend() {
clearErrorMessages();
var yourname = $('#yourname').val();
var errorMessage = "";
if (yourname == null || yourname == '') {
errorMessage += "Please enter your name<br />";
}
if (errorMessage != '') {
$('#errorMessage').html(errorMessage);
} else {
clearErrorMessages();
/* Ajax Post */
var formData = $("#tellAFriendForm").serialize();
$.ajax({
type: "GET",
url: "/Templates/include/new/ajax/tellAFriend.jsp",
data: formData,
success: function(data) {
if (data.error != null) {
$("#errorMessage").text(data.error);
} else {
$("#tellAFriendForm").fadeOut(1000);
$("#successMessage").text(data.success);
$("div").removeClass('display-none');
}
},
dataType: 'json'
});
}
}
[/code]
The ui-dialog widget will stay in the DOM as a hidden element even after the dialog is closed.
So, in order to isolate your two dialog functionalities from each other I'd suggest that you call:
forgottenPasswordDiv.dialog("destroy")
in your "closeForgottenPassword" function and
tellAFriendDiv.dialog("destroy")
in your "closeTellAFriend" function.
This will return the dialog back to its pre-init state (which is not harmful at all because you reinit it in your "open" functions.)

Resources