Logging out of Google when refreshing the page

I am currently working with the setup outlined below:

.service('googleService', ['$q', function ($q) {
    var self = this;

    this.load = function(){
        var deferred = $q.defer();
        gapi.load('auth2', function(){
            var auth2 = gapi.auth2.init();
            auth2.then(function(){ deferred.resolve(); });
            addAuth2Functions(auth2);
        });
        return deferred.promise;
    };

    function addAuth2Functions(auth2) {

        self.isSignedIn = function(){
            return auth2.isSignedIn.get();
        }

        self.signOut = function(){
            var deferred = $q.defer();
            auth2.signOut().then(deferred.resolve, deferred.reject);
            return deferred.promise;
        };

        self.getProfile = function() {
            if(auth2.isSignedIn.get()) return { signed_in: true, access_token: auth2.currentUser.get().Zi.id_token,profile: auth2.currentUser.get().getBasicProfile() };
            else return { signed_in: false };
        }

    }

}])

.config(function($stateProvider, $urlRouterProvider, $locationProvider) {

    $locationProvider.html5Mode(true);
    $urlRouterProvider.otherwise('/cloud');

    var guest = ['$q', '$rootScope', '$stateParams', 'googleService', function ($q, $rootScope, $stateParams, googleService) { 

        var deferred = $q.defer(); 

        googleService.load().then(function(){ 
            $q.when(googleService.isSignedIn()).then(function(r){ 
                if(r) deferred.reject(); 
                else deferred.resolve(); 
            }) 
        }); 

        return deferred.promise; 
    }];

    var authenticated = ['$q', '$rootScope', '$stateParams', 'googleService', function ($q, $rootScope, $stateParams, googleService) { 

        var deferred = $q.defer(); 

        googleService.load().then(function(){ 
            $q.when(googleService.getProfile()).then(function(p) { 
                if(p.signed_in) { 
                    deferred.resolve(); 
                    localStorage['access_token'] = p.access_token;
                    $rootScope.profile = p.profile; 
                } else deferred.reject(); 
            }) 
        }); 

        return deferred.promise; 
    }];

    $stateProvider

    .state('login', {
        url: '/',
        views: { 'main': { templateUrl: 'pages/templates/login.html', controller: 'login' } },
        resolve: { authenticated: guest }
    })

    .state('cloud', {
        url: '/cloud',
        views: { 'main': { templateUrl: 'pages/templates/cloud.html', controller: 'cloud' } },
        resolve: { authenticated: authenticated }
    })

})

.controller('login', ['$rootScope', '$scope', '$q', '$state', 'googleService', function ($rootScope, $scope, $q, $state, googleService) {
    $scope.options = { 'onsuccess': function(response) { $state.go('cloud'); } }
}])

.controller('cloud', ['$rootScope', '$scope', '$timeout', '$http', '$httpParamSerializerJQLike', function ($rootScope, $scope, $timeout, $http, $httpParamSerializerJQLike) { 

}]);

The issue I am facing is that after signing in using the Google sign-in button, googleService.getProfile() correctly indicates that I am signed in. However, upon refreshing the page, calling googleService.isSignedIn() returns false.

Is anyone able to spot a potential reason for this behavior and suggest any additional steps needed to ensure that Google remembers my sign-in status?

Answer №1

It seems like the main issue you're facing is the repetitive invocation of gapi.auth2.init() through googleService.load().

My recommendation would be to save the initialization promises for future use instead of generating them multiple times.

Additionally, you should include a condition to handle an expired access token.

.service('googleService', ['$q', function ($q) {
    const auth2InitPromise = $q(function(resolve) {
        gapi.load('auth2', function() {
            var auth2 = gapi.auth2.init();
            auth2.then(function() {
                resolve();
            });
        })
    });

    this.isSignedIn = function() {
        return auth2InitPromise.then(function() {
            return gapi.auth2.getAuthInstance().isSignedIn.get();
        });
    };

    this.signOut = function() {
        return auth2InitPromise.then(function() {
            const auth2 = gapi.auth2.getAuthInstance();
            return $q(function(resolve, reject) {
                auth2.signOut().then(resolve, reject);
            });
        });
    };

    this.getProfile = function() {
        return this.isSignedIn().then(function(isSignedIn) {
            if (isSignedIn) {
                const currentUser = gapi.auth2.getAuthInstance().currentUser.get();
                const authResponse = currentUser.getAuthResponse();
                return $q.when(authResponse.expires_at > Date.now() ? authResponse : currentUser.reloadAuthResponse()).then(function(ar) {
                    return {
                        signed_in: true,
                        access_token: ar.id_token,
                        profile: currentUser.getBasicProfile()
                    }                        
                });
            } else {
                return { signed_in: false };
            }
        });
    };

}])

Now, each method in your service (such as isSignedIn, signOut, and getProfile) returns a promise that resolves only after the initialization of the auth2 API, which now occurs just once.


Here's an example:

var authenticated = ['$q', '$rootScope', '$window', 'googleService', function ($q, $rootScope, $window, googleService) {
    return googleService.getProfile().then(function(p) {
        if (p.signed_in) {
            $window.localStorage.setItem('access_token', p.access_token);
            $rootScope.profile = p.profile;
            return true; // Resolvers should always resolve with something   
        } else {
            return $q.reject();
        }
    });
}];

Answer №2

Ensure that the authenticated is added as a dependency in your cloud controller. Additionally, within your googleService, make sure to call defer.resolve() only after setting

localStorage['access_token'] = p.access_token;
and $rootScope.profile = p.profile;

Answer №3

Hello, Please implement the following modifications in your code and inform me of the results.

.service('googleService', ['$q', function ($q) {
    var self = this;

    this.load = function(){
        gapi.load('auth2', callback);            
    };

    function callback(){
        var deferred = $q.defer();
        gapi.auth2.init()//insert your client credentials here
        .then(function(){ deferred.resolve(); });
        return deferred.promise;
    }


    self.isSignedIn=function (auth2){
        return auth2.isSignedIn.get();
    };

    self.signOut =function(auth2){
        var deferred = $q.defer();
        auth2.signOut().then(deferred.resolve, deferred.reject);
        return deferred.promise;
    };

    self.getProfile= function(auth2) {
        if(auth2.isSignedIn.get()) return { signed_in: true, access_token: auth2.currentUser.get().Zi.id_token,profile: auth2.currentUser.get().getBasicProfile() };
        else return { signed_in: false };
    };     


}])

   .config(function($stateProvider, $urlRouterProvider, $locationProvider) {

       $locationProvider.html5Mode(true);
       $urlRouterProvider.otherwise('/cloud');



       var guest = ['$q', '$rootScope', '$stateParams', 'googleService', function ($q, $rootScope, $stateParams, googleService) { 

           var deferred = $q.defer(); 
           googleService.load().then(function(){
               googleService.isSignedIn(gapi.auth2.getAuthInstance()).then(function(r){ 
                   if(r) deferred.reject(); 
                   else deferred.resolve(); 
               });   
           });



           return deferred.promise; 
       }];

       var authenticated = ['$q', '$rootScope', '$stateParams', 'googleService', function ($q, $rootScope, $stateParams, googleService) { 

           var deferred = $q.defer(); 

           googleService.load().then(function(){
               googleService.getProfile(gapi.auth2.getAuthInstance()).then(function(p) { 
                   if(p.signed_in) { 
                       deferred.resolve(); 
                       localStorage['access_token'] = p.access_token;
                       $rootScope.profile = p.profile; 
                   } else deferred.reject(); 
               });   
           });            

           return deferred.promise; 
       }];

       $stateProvider

       .state('login', {
           url: '/',
           views: { 'main': { templateUrl: 'pages/templates/login.html', controller: 'login' } },
           resolve: { authenticated: guest }
       })

       .state('cloud', {
           url: '/cloud',
           views: { 'main': { templateUrl: 'pages/templates/cloud.html', controller: 'cloud' } },
           resolve: { authenticated: authenticated }
       })

   })

   .controller('login', ['$rootScope', '$scope', '$q', '$state', 'googleService', function ($rootScope, $scope, $q, $state, googleService) {
       $scope.options = { 'onsuccess': function(response) { $state.go('cloud'); } }
   }])

   .controller('cloud', ['$rootScope', '$scope', '$timeout', '$http', '$httpParamSerializerJQLike', function ($rootScope, $scope, $timeout, $http, $httpParamSerializerJQLike) { 

   }]);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the reason behind the improved performance I experience in Chrome with the Developer Console open?

Currently, I am developing a small canvas game completely from scratch using pure JavaScript. This game utilizes a 2D lighting algorithm that is akin to the one found here. It features only one light source and 25 polygons, resulting in approximately 30,0 ...

Error: The function does not exist for collections.Map

I'm encountering a TypeError on my page: collections.Map is not a function. Below is my JavaScript code and I can't seem to figure out what the issue is. this.state = { collections: SHOP_DATA }; render() { const {collections} = this.sta ...

Issue with $watch in Angular Modal not triggering

Having trouble using $watch with a radio button located inside an AngularJS Modal. The $watch doesn't seem to work when the value changes within the modal. If I move the radio buttons outside the modal, the $watch functions as expected. You can see ...

What is the best way to automatically remove a Firebase database entry when a user has been inactive for a period of time, without logging out but simply not accessing the page for an extended duration?

Currently, when a user clicks 'logout', their session is terminated, and a database entry is removed. All other users can see that database entry, so the objective is for users to view each other's data only while they are logged in. For in ...

Not able to scroll to top in Angular 2 when changing routes

I need help figuring out how to automatically scroll to the top of my Angular 2 website when the route changes. I've attempted the code below, but unfortunately, it's not working as expected. When transitioning from one page to another, the page ...

Retrieve all elements from an array that have the highest frequency of occurrence

Consider an array like [1,4,3,1,6,5,1,4,4]. The element with the highest frequency in this array is 3. The goal is to select all elements from the array that have a frequency of 3, so in this case we would select [1,4]. To achieve this, one possible meth ...

Tips for interpreting a JSON object that has been returned

I'm currently working on creating a notification system. The process involves running an AJAX call that executes a PHP script to select all 'message' items where 'new=1'. The PHP array is then returned to the JavaScript function vi ...

The properties are not compatible with the expected types for a Next.js page

On my next.js website, I have created a page.tsx that should take in two props. Even though Visual Studio Code is not showing any errors, I encountered the following error message during the website build: Failed to compile. app/(Dashboard)/(practice)/pra ...

Clicking on "Ng-Click" will add a fresh row to the table using Angular

Is there a way to insert a new row into a table using ng-click? I currently have the following setup with the data stored in an array. Here is how my array looks. $scope.workflows = [{ Id: 1, Name: "Workflow Page 1", ...

Error in Webpack 5: Main module not found - Unable to locate './src'

When trying to build only Express and gql server-related files separately using webpack5, an error occurs during the process. ERROR in main Module not found: Error: Can't resolve './src' in '/Users/leedonghee/Dropbox/Project/observe ...

Is there a Rails 3 equivalent to $(document).ready() for ensuring that Highcharts loads correctly?

I am facing an issue with my highcharts chart not loading. I am looking for a way to delay the execution of the JavaScript file containing the chart data until after the partial has been passed into building the full page. Can someone provide guidance on ...

Scrolling through four limited list items automatically

Hey there! I am currently working on a design project. You can check it out here. I'm trying to replicate a section from another site, which you can see here. <div class="latest-winners-container"> <h3 class="header">Latest Winners< ...

Disposing of memory in THREE JS when switching between routes in VUE

Currently, I am delving into the world of VUE JS and working on a basic SPA that navigates through different pages. In my spare time, I have developed several THREE JS demos which unfortunately tend to slow down and eventually halt when switching between ...

Error encountered while generating Next.js static website in production

I am encountering errors when I try to export my project using npm run build. Oddly, everything works fine when I test with npm run dev. My code utilizes both getStaticProps and getStaticPath to fetch data from an API route. When I run npm run build I rec ...

Issue with AngularJS: $scope variables are not properly binding to the view when utilizing ng-repeat functionality

There seems to be an issue with data binding when using ng-repeat in my code. Despite the $scope variable being present when I console.log it, the data is not showing up in the view as expected. It's frustrating because I can't figure out what mi ...

Discover the way to retrieve PHP SESSION variable within JavaScript

I'm currently working on developing a platform for image uploads. As part of this project, I assign a unique identifier to each user upon login using $_SESSION['id'] in PHP. Now, I am looking for a way to verify if the $_SESSION['id&apo ...

The DIV element only becomes visible after a postback occurs

When I try to hide a DIV tag on the client side and then click submit to postback the data to the server side, the DIV reappears. Is there a way to solve this issue? ...

Tips for showcasing overflowing text in a menu list by rotating the item text

Imagine you have a TextMenuItem component, using MenuItem from the Material-UI library, that is part of a chain consisting of DropDownSearch > SimpleListMenu > FixedSizeList > TextMenuItem. In simple terms, this creates a searchable dropdown eleme ...

Create a vue-based browser extension that spans multiple pages

I've initiated my project using vite-plugin-web-extension Starting with a blank project using yarn create vite-plugin-web-extension, I managed to successfully load the extension in my Chrome browser. My goal is to include a login page and another pa ...

The predicament encountered with user registration in the realm of Node.js

I am encountering a problem with the sign-up route in node.js and MongoDB. Whenever I attempt to post data using Insomnia, it displays an error message. You can find the screenshot of the error [here](https://i.stack.imgur.com/qnGAv.png). Here is the code ...