Checking for signed in Google user with Google Sign-in - javascript

I'm working with the Google Sign-in library.
If I use Google's provided sign in button on my page, it quickly changes states to show that I am logged in before I've taken any action.
Is it possible to detect this signed in state without using Google's default button?
The main issue is that their button doesn't allow for checking for the hosted domain of the logged in account.

I was trying to use the GoogleAuth.currentUser.get() function to get the user, but as the documentation notes:
in a newly-initialized GoogleAuth instance, the current user has not been set. Use the currentUser.listen() method or the GoogleAuth.then() to get an initialized GoogleAuth instance.
Using GoogleAuth.then(onInit, onFailure) as mentioned above correctly retrieves the logged in state of the user.
/**
* The Sign-In client object.
*/
var auth2;
/**
* Initializes the Sign-In client.
*/
var initClient = function() {
gapi.load('auth2', function(){
/**
* Retrieve the singleton for the GoogleAuth library and set up the
* client.
*/
auth2 = gapi.auth2.init({
client_id: CLIENT_ID,
scope: 'profile'
});
// Called once auth2 has finished initializing
auth2.then(checkForLoggedInUser, onFailure);
});
};
function checkForLoggedInUser() {
var user = auth2.currentUser.get();
var profile = user.getBasicProfile();
console.log('Email: ' + profile.getEmail());
}

You can use the GoogleAuth.isSignedIn.get() method:
// 1. Make gapi.auth2 available (using gapi.load("auth2", ...))
// 2. Initialize the library (using gapi.init({ ... }))
const isSignedIn = gapi.auth2.getAuthInstance().isSignedIn.get();
isSignedIn is true if the user is signed to Google, otherwise false.

Related

how to work with google calender API in Nodes js and React

my organization is creating a hotel booking website for another company. Apart from the website we are helping this company to create, They also have their rooms or spaces listed on the external website, Airbnb precisely. so they have the same spaces and hotels listed on the website we created for them and also in Airbnb. so we need to implement a way that won't allow their clients to book the same space or room at the same range of time. I.E if a client books a room at 9:45 am in the morning and will lodge only for 2 days, that room should no longer be available for the dates range the other user has booked it. So we decided to use the google calendar API as a middle man between our own website and AirbnB. if a user books any room or space in our website, on payment successful on the client at our ends here, The days the client wanna lodge should be added to the google calendar API to be exported to Airbnb and this should avoid bringing that consent screen google normally brings out to authenticate as we don't need to show anything to the client, we just want everything to be done underground. Most importantly I wanna do this using React.
I followed one node js video tutorial and he was able to create and read events successfully. he used the googleOauth2 playground API for authenticating. The API gave us a client Id, client Secret and most importantly a refresh token that would be used mainly to authenticate. This is the code below
// Require google from googleapis package.
const { google } = require('googleapis')
// Require oAuth2 from our google instance.
const { OAuth2 } = google.auth
// Create a new instance of oAuth and set our Client ID & Client Secret.
const oAuth2Client = new OAuth2(
'YOUR CLIENT ID GOES HERE',
'YOUR CLIENT SECRET GOES HERE'
)
// Call the setCredentials method on our oAuth2Client instance and set our refresh token.
oAuth2Client.setCredentials({
refresh_token: 'YOUR REFRESH TOKEN GOES HERE',
})
// Create a new calender instance.
const calendar = google.calendar({ version: 'v3', auth: oAuth2Client })
I didn't post everything because the remaining codes is just creating events and the likes. So I was following this format to make the events work here in react but I was unable to pass the authenticate block in react.
According to the documentation for javascript
It states that I have to add the script src file below to make gapi works for javascript
<script async defer type='text/Javascript' src="https://apis.google.com/js/api.js"></script>
But the problem now is how to implement the authentication using the refresh token available that was downloaded as json in react. The below code is how this was implemented using client and api key always showing windows for users to login before they can create events which in my case, I dont want
// Client ID and API key from the Developer Console
var CLIENT_ID = '<YOUR_CLIENT_ID>';
var API_KEY = '<YOUR_API_KEY>';
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
/**
* Called when the signed in status changes, to update the UI
* appropriately. After a sign-in, the API is called.
*/
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
listUpcomingEvents();
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
function initClient() {
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
}, function(error) {
appendPre(JSON.stringify(error, null, 2));
});
}
So the below is what have done but am stuck as I dont know what to else from here. I dont even know if what am doing is right or wrong
useEffect(()=>{
gapi.load("client:auth2", () => {
gapi.client
.init({
clientId: "myClientId",
clientKey: "myClientKey",
})
.setToken({
access_token:
"myRefreshToken",
});
});
},[])
I need to get pass authentication to be able to create, read events in google calendar in REACT

Add Google authentication to Firebase Real Time Database

I'm using the Firebase Real Time Database and I need to add user authentication to it. Users can only login with Google as a provider.
Current database mode:
{
"rules": {
".read": true,
".write": true
}
}
New mode should be like this:
// These rules grant access to a node matching the authenticated
// user's ID from the Firebase auth token
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
What should I use to authenticate in my case? userID, Google providerID or a token like described here?
This is the function without authentication to store data:
createMeetup ({commit, getters}, payload) {
console.log('index.js -> createMeetup')
const meetup = {
title: payload.title,
}
let imageUrl
let key
firebase.database().ref('meetups').push(meetup)
.then((data) => {
key = data.key
return key
})
.then(() => {
commit('createMeetup', {
...meetup,
imageUrl: imageUrl,
id: key
})
})
.catch((error) => {
console.log(error)
})
},
For your use case it seems like you need to sort out a few steps. I'm guessing your application can already connect/use Firebase, but these are essentially it:
Step 1 - Connecting
Connect to Firebase using your API key/config as per usual, should look something like the following.
firebase.initializeApp(config)
See also: https://firebase.google.com/docs/web/setup
You probably already have this somewhere. This does not change, but if you would apply the rules as described your users would not be able to use Firebase after just connecting.
Step 2 - Authenticating
This is basically telling Firebase who is connected. This must be done with a token/method Firebase can verify. Using a Google ID is the most common method.
With an existing Google ID / user login
// Initialize a generate OAuth provider with a `google.com` providerId.
var provider = new firebase.auth.OAuthProvider('google.com');
var credential = provider.credential(googleUser.getAuthResponse().id_token);
firebase.auth().signInWithCredential(credential)
See also: https://firebase.google.com/docs/reference/js/firebase.auth.OAuthProvider#credential
Or make Firebase SDK do the login flow
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
})
See also: https://firebase.google.com/docs/auth/web/google-signin
This last option is preferred / suggested by the documentation you referenced.
If, as you described, users can already login with Google to your app for other functionalities then you should already have a login flow somewhere. Depending on your situation it might be advisable to let the Firebase SDK / library take over this process for simplicity in your application.
Step 3 - Using the database
Lastly, after authenticating users and applying the rules you suggested you will need to also make sure the paths you write to are within those accessible by the current user. You can put this in a simple function to make it easier.
const getUserRef = (ref) => {
const user = firebase.auth().currentUser;
return firebase.database().ref(`/users/${user.uid}/${ref}/`);
}
You should of course not be retrieving the current user every time you want to get a database reference, but I think this clearly illustrates the steps that need to be taken.
You can allow users to login/auth using multiple methods. Then you can merge them together to a single account as described here:
https://firebase.google.com/docs/auth/web/account-linking
So really it boils down to two options:
Allow users to login with multiple methods such as Facebook, Google, Github, basic username/password, etc.
Or allow only a single login method such as Google only.
Whichever options you pick will help you decide which ID to use.
The auth rules in your question are only stating that the users can read/write their own (presumably) user data.
I assume that you are rather looking for a solution to authorize the user to create meetup data and you should crerate rules similar to this:
These rules allow any user that is logged in to create meetups
{
"rules": {
"meetups": {
"$meetupId": {
".read": "auth.uid != null",
".write": "auth.uid != null"
}
}
}
}
Your code-snippet that pushes new meetup data to the database will automatically try and succeed or fail depending on whether the user was logged in or not. You don't need to specifically tell Firebase in which way the user was logged in. Firebase SDK will take care of the authentication for you.
But if you do want to provide different mechanisms depending on which login type that the user is authenticated with, you can check it in the rules. For example if you want to make sure that the user is not just "anonymously" logged in.
See the documentation: https://firebase.google.com/docs/database/security/user-security#section-variable
the documentation has you covered there: Authenticate Using Google Sign-In with JavaScript.
You can let your users authenticate with Firebase using their Google Accounts by integrating Google Sign-In into your app. You can integrate Google Sign-In either by using the Firebase SDK to carry out the sign-in flow, or by carrying out the Google Sign-In flow manually and passing the resulting ID token to Firebase.
Before you begin:
Add Firebase to your JavaScript project.
Enable Google Sign-In in the Firebase console:
In the Firebase console, open the Auth section.
On the Sign in method tab, enable the Google sign-in method and click Save.
Handle the sign-in flow with the Firebase SDK
If you are building a web app, the easiest way to authenticate your users with
Firebase using their Google Accounts is to handle the sign-in flow with the
Firebase JavaScript SDK. (If you want to authenticate a user in Node.js or
other non-browser environment, you must handle the sign-in flow manually.)
To handle the sign-in flow with the Firebase JavaScript SDK, follow these steps:
Create an instance of the Google provider object:
var provider = new firebase.auth.GoogleAuthProvider();
Optional: Specify additional OAuth 2.0 scopes that you want to request from the authentication provider. To add a scope, call addScope().
For example:
provider.addScope('https://www.googleapis.com/auth/contacts.readonly');
See the authentication provider documentation.
Optional: To localize the provider's OAuth flow to the user's preferred language without explicitly passing the relevant custom OAuth parameters, update the language code on the Auth instance before starting the OAuth flow.
For example:
firebase.auth().languageCode = 'pt';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();
Optional: Specify additional custom OAuth provider parameters that you want to send with the OAuth request. To add a custom parameter, call setCustomParameters on the initialized provider with an object containing the key as specified by the OAuth provider documentation and the corresponding value.
For example:
provider.setCustomParameters({
'login_hint': 'user#example.com'
});
Reserved required OAuth parameters are not allowed and will be ignored. See the authentication provider reference for more details.
Authenticate with Firebase using the Google provider object. You can prompt your users to sign in with their Google Accounts either by opening a pop-up window or by redirecting to the sign-in page. The redirect method is preferred on mobile devices.
To sign in with a pop-up window, call signInWithPopup:
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
Also notice that you can retrieve the Google provider's OAuth token which can be used to fetch additional data using the Google APIs.
This is also where you can catch and handle errors. For a list of error codes have a look at the Auth Reference Docs.
To sign in by redirecting to the sign-in page, call signInWithRedirect:
firebase.auth().signInWithRedirect(provider);
Then, you can also retrieve the Google provider's OAuth token by calling getRedirectResult() when your page loads:
firebase.auth().getRedirectResult().then(function(result) {
if (result.credential) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// ...
}
// The signed-in user info.
var user = result.user;
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});

Google sign in API does not work on Mozilla Firefox

I am currently handling a web app that requires the user to sign in using their google account to gain access to the core functionalities. When using Google Chrome everything works the way it's expected to work: The user clicks "Sign In", a pop-up opens with Google sign in form, the user signs in, and he will be transferred to the main page. (good)
HOWEVER
When using Mozilla Firefox 38.0.1, the web app cannot be used in any way because when the user clicks "Sign In", it does nothing. Literally nothing, not even an error on the console.
Here is the login button:
//head
<meta name="google-signin-client_id" content="{CLIENT ID}.apps.googleusercontent.com">
//body
<button class="g-signin2 login-button" data-onsuccess="onSignIn"></button>
Is there a currently known issue with Firefox and Google Sign In API?
Ok, found the solution: I followed this. Basically, I didnt use the easy integration of the Google SignIn and I just created a custom handler and listeners. I kept the original buttons because it is required and just added this javascript:
HTML
<script src="https://apis.google.com/js/plus.js?onload=appStart"></script>
JS
//googleSignIn.js
var auth2; // The Sign-In object.
var googleUser; // The current user.
/**
* Calls startAuth after Sign in V2 finishes setting up.
*/
var appStart = function() {
console.log('appStart()')
gapi.load('auth2', initSigninV2);
};
/**
* Initializes Signin v2 and sets up listeners.
*/
var initSigninV2 = function() {
auth2 = gapi.auth2.getAuthInstance({
client_id: '{CLIENT ID}.apps.googleusercontent.com',
scope: 'profile'
});
// Listen for sign-in state changes.
auth2.isSignedIn.listen(signinChanged);
// Listen for changes to current user.
auth2.currentUser.listen(userChanged);
// Sign in the user if they are currently signed in.
if (auth2.isSignedIn.get() == true) {
auth2.signIn();
}
};
/**
* Listener method for sign-out live value.
*
* #param {boolean} val the updated signed out state.
*/
var signinChanged = function (val) {
console.log('Signin state changed to ', val);
};
/**
* Listener method for when the user changes.
*
* #param {GoogleUser} user the updated user.
*/
var userChanged = function (user) {
console.log('User now: ', user);
googleUser = user;
};
$('.login-button').on('click', function() {
console.log('signing in')
auth2.signIn().then(function(user) {
//callback to handle sign in
onSignIn(user);
});
})
I'm not sure what caused the issue of the Google Sign In to not work on mozilla. If anyone knows this to be a known issue please let me know in the comments.
Bottomline: easy integration of Google Sign In did not work on Mozilla. Had to integrate using listeners.

How to manage google sign-in session (Google Sign-In JavaScript client)

im trying to implement google sign-in using their new API : https://developers.google.com/identity/sign-in/web/
Sign-in and Sign-out work fine.
My problem is that i dont know how to manage a session on other pages without a server side.
So i tried this code - https://developers.google.com/identity/sign-in/web/session-state
And it doesnt work well for me.
I dont want to have the google sign in button in every page. If i remove the "auth2.attachClickHandler.." part the whole code doesnt work.
All i want is to indicate in other pages (not in the page with the google button) if a user is still connected to or not.
Can you help me?
EDIT:
I tried the following code suggested in the answers but i get an error that says: " Uncaught TypeError: Cannot read property 'init' of undefined"
Code:
var auth2 = gapi.auth2.init({
client_id : 'ID.apps.googleusercontent.com'
});
auth2.then(function() {
var isSignedIn = auth2.isSignedIn.get();
var currentUser = auth2.currentUser.get();
if (isSignedIn) {
console.log("signed in");
// User is signed in.
// Pass currentUser to onSignIn callback.
} else {
console.log("NOT signed in");
// User is not signed in.
// call auth2.attachClickHandler
// or even better call gapi.signin2.render
}
});
You can load gapi.auth2 on all pages and call:
var auth2 = gapi.auth2.init(...);
auth2.then(function() {
var isSignedIn = auth2.isSignedIn.get();
var currentUser = auth2.currentUser.get();
if (isSignedIn) {
// User is signed in.
// Pass currentUser to onSignIn callback.
} else {
// User is not signed in.
// call auth2.attachClickHandler
// or even better call gapi.signin2.render
}
});
In this solution sign in button is displayed only when user is not signed in.

AngularFire: Resuming an anonymous session

From the Simple Web Login docs, it claims you can resume a session by doing the following:
var auth = new FirebaseSimpleLogin(chatRef, function(error, user) {
...
});
Is there an equivalent for AngularFire?
The $firebaseSimpleLogin constructor takes a firebase reference as its only parameter..
Specifically, what I'm trying to do is login once anonymously and resume that login on a full page refresh. Is that achievable?
Whether or not your auth session is preserved is determined by the parameters you pass into the login method. Whether you use FirebaseSimpleLogin or $firebaseSimpleLogin is irrelevant here.
var auth = $firebaseSimpleLogin(ref);
$rootScope.$on('$firebaseSimpleLogin:login', function(user) {
console.log('logged in', user.uid);
});
// automagically logs in the next time you call $firebaseSimpleLogin() after page refresh
auth.$login('anonymous', { rememberMe: true });
// does not automagically log in
auth.$login('anonymous');
UPDATE As of Angular 1.x and Firebase 2.x this syntax and behavior has changed.
From the remember attribute in Firebase docs:
If not specified - or set to default - sessions are persisted for as
long as you have configured in the Login & Auth tab of your App
Dashboard. To limit persistence to the lifetime of the current window,
set this to sessionOnly. A value of none will not persist
authentication data at all and will end authentication as soon as the
page is closed.
var auth = $firebaseAuth(ref);
$firebaseAuth.$onAuth(function(user) {
console.log('logged ' + (user? 'in' : 'out'), user && user.uid);
});
// stays logged in for length specified in the app dashboard
auth.$authAnonymously();
// stays logged in until the browser closes
auth.$authAnonymously({ remember: 'sessionOnly' });
// does not stay logged in on page refresh
auth.$authAnonymously({ remember: 'none' });

Categories