Implement sign out from google Oauth - oauth

How to sign out from sign-in-with-google app. I want to sign out in such a way that it again ask for password when again sign in with google.
I don't want to remove account from my browser.
I just simply want to forget my browser.

Sign out
<script>
function signOut() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
</script>
Its from the official document https://developers.google.com/identity/sign-in/web/sign-in#sign_out_a_user.
If you want to logout of an application as a user of any website you can do it in your account's security preferences: https://myaccount.google.com/permissions

Related

Set default domain when using "Sign In With Google"

Using the instructions for Google sign in located here, We are implementing the "Sign in with Google" button.
This implementation has been successful, however, we want to set a default domain other than gmail.com as this will be used by our Gsuite for education users. This would make it so that users can click the sign in button and just type their username, instead of username#gSuiteDomain.com
When this button is clicked:
The user is redirected to:
How do we make it so the second image defaults to our gSuite domain instead of gmail.com?
I am pretty sure is you set the "hd" parameter to the G Suite domain name that it will work.
Please let us know if that works.
You can't use the simple directions at the location I linked in the question, as it is only for a basic minimum authentication.
For customization, you need to access the full client API here (server side validation can stay the same.)
This allows you to pass information to the init functions:
<script src="https://apis.google.com/js/platform.js?onload=onLoadCallback" async defer></script>
Then:
window.onLoadCallback = function () {
gapi.load('auth2', initSigninV2);
function initSigninV2() {
gapi.auth2.init({
client_id: 'Your_client_id',
hosted_domain: "YourHostedDomain.com"
}).then(function (authInstance) {
if (authInstance != null && authInstance != undefined) {
gapi.signin2.render("IDOfSignInButton", { onsuccess: onSignIn });
}
});
}
The rest is the same as in the original tutorial

How to force account selection when using social provider login in Lock

I am having trouble clearing the last login when using social providers.
Currently using Lock with the following options:
var options = {
rememberLastLogin: false,
auth: {
sso: false,
redirect: false
}
};
var lock = new Auth0Lock('clientID', 'account.auth0.com', options);
The issue is that when executing the next steps it always logins with the same account:
Call lock.show
Select social login provider (Google)
Attempt login with account A [non authorized account]
Lock shows "You are not allowed to access this application." [expected result]
Click Google button again and it still tries to log into the same account A (Lock does not offer a way to try different login from same social provider)
Close Lock and reopen it
Click Google button and it still uses same login account A (no option to enter new account)
What can I do to be able to select a different account?
When you use a social login provider the automatic sign-in is handled by the provider in question. Disabling the sso option and rememberLastLogin will mean Auth0 will not try to login you automatically or provide any information about who login for the last time.
When you login with Google the first time, Google created a session and next requests will automatically use that session by default.
However, Google supports an option that will allow you to choose the behavior you want, in this case it seems you want for the user to be able to select another account, which can be accomplished by passing the following option prompt=select_account (see other options here) in the Google login request.
You can achieve this in Auth0 Lock by providing this option in the auth.params object. Updated example below:
var options = {
rememberLastLogin: false,
auth: {
sso: false,
redirect: false,
params: { prompt: 'select_account' }
}
};
var lock = new Auth0Lock('clientId', '[tenant].auth0.com', options);
Or if you use Auth0.WebAuth then you need to pass param to authorization call:
auth0Instance.web.authorize({
prompt: 'select_account'
})

Can't hit Google plus api after oauth with Firebase

2 hours trying to get this to work and I can't. Firebase authenticates the user just fine, but then it can't fetch anything from the Google Plus API.
The error you will get:
{
domain: "global"
location: "Authorization"
locationType: "header"
message: "Invalid Credentials"
reason: "authError"
}
The code is this:
Auth.$authWithOAuthPopup(provider, {
scope: ['profile', 'email']
}).then(function(authData) {
console.log(authData.token);
gapi.client.setApiKey('<APIKEY>');
gapi.client.load('plus','v1', function(){
var request = gapi.client.plus.people.get({
'userId': 'me'
});
request.execute(function(resp) {
console.log('Retrieved profile for:' + resp.displayName);
debugger;
});
});
}, showError);
It must have something to do with Firebase making the call on our behalf. Because this codepen, in which we do our own authentication, works fine:
http://codepen.io/morgs32/pen/KVgzBw
Don't forget to set clientId and apiKey in the codepen.
If you can figure this one out you're gonna get gold on christmas.
You're trying to use authData.token to access Google. But authData.token is a JWT token for accessing Firebase.
To access Google, you should use authData.google.accessToken.
Also see this page in the Firebase documentation on using the Google provider.

Is it possible to limit the access given by a user so that it's read-only

I'm trying to use the YouTube Data API V2.0 to pull data insights for the videos/channels of our client. I have a developer key and a token that my client generates, and successfully figured out how to retrieve that information. My problem is, when my client uses the app for YouTube token generation, we are asking for an access that means EVERYTHING and to be able to "manage" their accounts.
This is a major concern for the client and they don't want us to have this kind of complete access. Is there a way to get a token generated with only read-only permission?
Thanks very much for any help!
I have successfully used https://googleapis.com/auth/youtube.readonly as a scope; if you ask for just that scope during the initial oAuth flow (and NOT for https://googleapis.com/auth/youtube at the same time, as that is the management scope which will override the readonly scope), then you will get a 403 error whenever attempting an action that requires management permissions (inserting, uploading, updating, deleting).
The google-api clients for v3 handle this quite smoothly, if you're using them. If you have written your own oAuth flow control, just make sure you have the sole readonly scope when requesting the initial token.
EDIT IN RESPONSE TO COMMENT: To view this in action (I'll use javascript to show), you can create a simple demo using the sample code provided by the API docs. Here's the general process:
1) In the Google API console, create a 'project' and authorize the YouTube API for that project (under the Services tab). Additionally,create a client ID for web applications (under the API access tab) and add in your domain as an authorized Javascript domain.
2) On your server, create and HTML file to serve as your interface (in this sample, it is designed to let you create a new playlist and add items to it). Here's the code, straight from the docs:
<!doctype html>
<html>
<head>
<title>Playlist Updates</title>
</head>
<body>
<div id="login-container" class="pre-auth">This application requires access to your YouTube account.
Please authorize to continue.
</div>
<div id="buttons">
<button id="playlist-button" disabled onclick="createPlaylist()">Create a new Private Playlist</button>
<br>
<label>Current Playlist Id: <input id="playlist-id" value='' type="text"/></label>
<br>
<label>Video Id: <input id="video-id" value='GZG9G5txtaE' type="text"/></label><button onclick="addVideoToPlaylist()">Add to current playlist</button>
</div>
<h3>Playlist: <span id="playlist-title"></span></h3>
<p id="playlist-description"></p>
<div id="playlist-container">
<span id="status">No Videos</span>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="auth.js"></script>
<script src="playlist_updates.js"></script>
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
</body>
</html>
3) In that same location, create the script "playlist_updates.js" with this code (again, straight from the docs):
// Some variables to remember state.
var playlistId, channelId;
// Once the api loads call a function to get the channel information.
function handleAPILoaded() {
enableForm();
}
// Enable a form to create a playlist.
function enableForm() {
$('#playlist-button').attr('disabled', false);
}
// Create a private playlist.
function createPlaylist() {
var request = gapi.client.youtube.playlists.insert({
part: 'snippet,status',
resource: {
snippet: {
title: 'Test Playlist',
description: 'A private playlist created with the YouTube API'
},
status: {
privacyStatus: 'private'
}
}
});
request.execute(function(response) {
var result = response.result;
if (result) {
playlistId = result.id;
$('#playlist-id').val(playlistId);
$('#playlist-title').html(result.snippet.title);
$('#playlist-description').html(result.snippet.description);
} else {
$('#status').html('Could not create playlist');
}
});
}
// Add a video id from a form to a playlist.
function addVideoToPlaylist() {
addToPlaylist($('#video-id').val());
}
// Add a video to a playlist.
function addToPlaylist(id, startPos, endPos) {
var details = {
videoId: id,
kind: 'youtube#video'
}
if (startPos != undefined) {
details['startAt'] = startPos;
}
if (endPos != undefined) {
details['endAt'] = endPos;
}
var request = gapi.client.youtube.playlistItems.insert({
part: 'snippet',
resource: {
snippet: {
playlistId: playlistId,
resourceId: details
}
}
});
request.execute(function(response) {
$('#status').html('<pre>' + JSON.stringify(response.result) + '</pre>');
});
}
Finally, create the file "auth.js" -- this is the code that actually does the oAuth2 flow:
// The client id is obtained from the Google APIs Console at https://code.google.com/apis/console
// If you run access this code from a server other than http://localhost, you need to register
// your own client id.
var OAUTH2_CLIENT_ID = '__YOUR_CLIENT_ID__';
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube'
];
// This callback is invoked by the Google APIs JS client automatically when it is loaded.
googleApiClientReady = function() {
gapi.auth.init(function() {
window.setTimeout(checkAuth, 1);
});
}
// Attempt the immediate OAuth 2 client flow as soon as the page is loaded.
// If the currently logged in Google Account has previously authorized OAUTH2_CLIENT_ID, then
// it will succeed with no user intervention. Otherwise, it will fail and the user interface
// to prompt for authorization needs to be displayed.
function checkAuth() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: true
}, handleAuthResult);
}
// Handles the result of a gapi.auth.authorize() call.
function handleAuthResult(authResult) {
if (authResult) {
// Auth was successful; hide the things related to prompting for auth and show the things
// that should be visible after auth succeeds.
$('.pre-auth').hide();
loadAPIClientInterfaces();
} else {
// Make the #login-link clickable, and attempt a non-immediate OAuth 2 client flow.
// The current function will be called when that flow is complete.
$('#login-link').click(function() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: false
}, handleAuthResult);
});
}
}
// Loads the client interface for the YouTube Analytics and Data APIs.
// This is required before using the Google APIs JS client; more info is available at
// http://code.google.com/p/google-api-javascript-client/wiki/GettingStarted#Loading_the_Client
function loadAPIClientInterfaces() {
gapi.client.load('youtube', 'v3', function() {
handleAPILoaded();
});
}
Note in there the OAUTH2_SCOPES constant. It's set to allow full management access, so if you then visit the html page in your browser and click on the 'authorize' link, you should see the window asking you to grant your domain access to manage your YouTube account. Do this, and then the code becomes functional ... you can add playlists and playlist items to your heart's content.
If you, however, then modify auth.js so that the OAUTH2_SCOPES looks like this:
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube.readonly'
];
and clear your cookies (to avoid inheriting the permissions you already granted ... just closing the browser and relaunching ought to be enough), then try again (visit the HTML, click the authorize link), you'll see that this time it's asking you to grant permission only to VIEW the account rather than manage it. If you grant that permission, then when you try to add a playlist through the interface you'll get an error message appearing that says you can't create the playlist.
If you're not using javascript, but instead a server-side language, as I mentioned the gapi clients are quite smooth. However, the handling of oAuth2 scope in these clients is not quite as transparent, and they're by design 'greedy' (in that, as it abstracts a service endpoint to an object, it will request the most thorough scope it needs to do any of the actions at that endpoint ... so even if you only intend to do list calls, if the service has an update action as well the client will request full management privileges). This can be modified, though, if you want to get into the client code -- or you could use it as a model for creating your own simplified client that you can granularly control in terms of scope.
That's about as thorough as I can be without knowing your underlying technologies. Hope the explanation helps!

Facebook Authorization on Rails app: why do we need to do Both server and client side authorization?

In Ryan's Railscast on Facebook authorization, he adds some Facebook SDK javascript at the end to "degrade facebook client side authorization with server side authorization." However, I do not see the use of it. If we already set up the authorization from the server side using omniauth, why do we have to add the client-side authorization again? What difference does it make?
The referenced javascript code is (From the linked Railscast):
jQuery ->
$('body').prepend('<div id="fb-root"></div>')
$.ajax
url: "#{window.location.protocol}//connect.facebook.net/en_US/all.js"
dataType: 'script'
cache: true
window.fbAsyncInit = ->
FB.init(appId: '<%= ENV["FACEBOOK_APP_ID"] %>', cookie: true)
$('#sign_in').click (e) ->
e.preventDefault()
FB.login (response) ->
window.location = '/auth/facebook/callback' if response.authResponse
$('#sign_out').click (e) ->
FB.getLoginStatus (response) ->
FB.logout() if response.authResponse
true
UPDATE:
One of the reasons we need to integrate FB.login authorization with the server-side authorization might be that the Omniauth server-side authorization does NOT work if it's accessed within the Facebook iFrame. If the user accesses the application for the first time, the application must ask for permissions; however, oAuth permission dialog cannot be loaded within the iFrame to prevent clickjacking. Calling FB.login can avoid such problem, because it will show the permission box as a popup(Omniauth popup option will not work).
So now I have a genuine reason to integrate client-side authorization, but the code from Railscasts does not work with my current settings. I've chosen to do it the following way.
Right now, I have the following script in my application.html.erb:
<script>
// Additional JS functions here
window.fbAsyncInit = function() {
FB.init({
appId : <%= ENV['FACEBOOK_KEY'] %>, // App ID
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
</script>
And in my view, I have the following link invoking the Facebook log in action:
<%= link_to 'log in with facebook', '/auth/facebook', id: 'fb_log_in_link' %>
I add the following script to the view page where I have the login link.
function login() {
FB.login(function(response) {
if (response.authResponse) {
window.location = '/auth/facebook/callback'
}
});
}
Also, I need to change the link to call the function instead of directing to /auth/facebook/
<%= link_to_function 'log in with facebook', 'login()' %>
Done! The server-side and client-side authorization are fully integrated. Since I was still confused after watching Ryan's Railscast, I want to add a little bit of explanation for those who might be also confused.
The way this works:
Facebook SDK is initailized when the while the page is loaded.
The user clicks the "log in with Facebook" link.
FB.login function is called by the link, and the user goes through all the permissions process (e.g. permission dialog showing up asking for the user's permissions).
Then, the user is directed to /auth/facebook/callback. From routes.rb we have the line match 'auth/:provider/callback', to: 'sessions#create'. Therefore, now the server will either create a new user or simply create a session if the user has already registered before.
Done! The user is logged in.
Merging server-side and client-side authorization has two major advantages:
1. If the user is logged into the application either inside Facebook(via appcenter) he will be logged into the application outside Facebook as well. Vice versa, if the user logs in outside Facebook, he will be logged in automatically if he accesses it within Facebook after.
2. Logging in with /auth/facebook does not work if the user logs in within Facebook iFrame. To prevent clickjacking Facebook prohibits prompting users to auth permissions dialog within Facebook iFrame. The only way to avoid this is to open the dialog in a separate popup, and logging in with FB.login solves the problem.
the short answer is - you don't.
you can choose between client side login (via javascript SDK) and server side login using omniauth.
the disadventage of server-side login is overloading the server for a call you can do from the client.
the advantage is that usually the token is longer (3 months token and not 1-2 hours like client side).
i suggest combine the two. use the client side for initial login, once you do that have an async call from the server side for extended token (only if you have to).
It just says,
Facebook provides a JavaScript SDK that we can use to authenticate a user on the client-side so that it doesn’t look to them like they’ve left our application then returned.
It means that this is for the client side understanding that when user returned from the application, it doesn't look like that they have indeed left it.

Resources