anthonyjgrove / react-google-login

A React Google Login Component
https://anthonyjgrove.github.io/react-google-login
MIT License
1.85k stars 426 forks source link

Question: Couldn't we avoid to show the logging button in the case that the user already logged in? #350

Open JoseFMP opened 4 years ago

JoseFMP commented 4 years ago

Instead of showing the button to make the user log in every time, it'd be great if with a client-side script we can double check if the user was already logged in with its Google account, and then we can decide to skip showing the button.

sahilsk11 commented 4 years ago

Following - would love to see this as well. Can we use any of the hooks to check for current log in status?

sahilsk11 commented 4 years ago

Alright, I inspected the source code and dug around a lot and came up with the following solution.

Firstly, add the following to your index.html in the public folder (assuming you are using create-react-app; if not, find another way to include it)

<script src="https://apis.google.com/js/api.js" async defer></script>

Next, dig into whatever component is managing the page (in my case, this was App.js). Add the following block.

const [login, updateLogin] = useState(null);
useEffect(() => {
      setTimeout(() => {
        window.gapi.load('auth2', () => {
          window.gapi.auth2.init({ client_id: clientId }).then(
            res => {
              const signedIn = res.isSignedIn.get()
              console.log(signedIn)
              updateLogin(signedIn);
            }
          )
        });
      }, 100);
  }, []);

The login state will now manage whether the user is logged in or not.

Notice the setTimeout. This is because the window.gapi.load can be buggy and not load correctly (see here)

Also notice the login is set to null by default. I have configured my component so that when login === null I display a loading animation, since they are not authenticated nor redirected yet.

Let me know if this helps!

abbathaw commented 4 years ago

@sahilsk11 Thanks for this snippet, but I wanted to clarify something.. I initially thought I wanted to do sth like you mentioned, but I realised using isSignedIn={true} does the same desired behaviour of logging in the user. Is there something missing that I misunderstood that is not covered?

 <GoogleLogin
            clientId={GOOGLE_CLIENT_ID}
            onSuccess={onSuccess}
            onFailure={onFailure}
            cookiePolicy={'single_host_origin'}
            isSignedIn={true}
        />
sahilsk11 commented 4 years ago

@abbathaw great question! My application actually used two different pages. One was the default, root page, the other was the login page. So when a user logged into the website for the first time, I needed a way to check if they were logged in before a) loading content on the page or b) routing them to the login page. If your app runs on a single page, or if the login page is the default landing page, this should work fine!

Let me know if that answers your question.

abbathaw commented 4 years ago

ah ok..thanks for your answer and clarification. It makes sense now. Yeah, my app is an SPA.

rosghub commented 4 years ago

@sahilsk11 A better approach (or more abstract from the gapi client library) would be using the useGoogleLogin hook in your master component (or provider):

export default function App() {
    const [isSignedIn, setSignedIn] = useState(false);
    const googleLogin = useGoogleLogin({
        clientId: GOOGLE_CLIENT_ID,
        onSuccess: (res) => {
            setSignedIn(true);
        },
        cookiePolicy: 'single_host_origin',
        isSignedIn: true
    });
...
    // Conditionally render a sign in button if not signed in

The hook will load the gapi script for you in a useEffect, call the auth2.init function and then the isSignedIn prop will tell the library to call your onSuccess method.

AsebWebDev commented 4 years ago

The solutions by @rosghub, @abbathaw and @sahilsk11 are all using the google-api as I understand it.

Right now each time I refresh my page in the browser, the component is checking the google-API, which takes some time to load. When I just logged in via Google and directly refresh my page its annoying that I have to wait for another web request to resolve (even with isSignedIn: true). Is there any way I could quickly check for an existing valid token in my browser, without checking the google api and without creating a security issue? Like some session management on my client?

dejavu1987 commented 3 years ago

@sahilsk11 A better approach (or more abstract from the gapi client library) would be using the useGoogleLogin hook in your master component (or provider):

export default function App() {
    const [isSignedIn, setSignedIn] = useState(false);
    const googleLogin = useGoogleLogin({
        clientId: GOOGLE_CLIENT_ID,
        onSuccess: (res) => {
            setSignedIn(true);
        },
        cookiePolicy: 'single_host_origin',
        isSignedIn: true
    });
...
    // Conditionally render a sign in button if not signed in

The hook will load the gapi script for you in a useEffect, call the auth2.init function and then the isSignedIn prop will tell the library to call your onSuccess method.

I think react-google-login needs to be discontinued in favor of https://github.com/asyarb/react-use-googlelogin This component is very limited in its own scope, its not built for anything more complicated than having this button on a view, everything else becomes really complicated, at the end if you are going the context/provider route anyway, react-use-googlelogin is the way to go, all you need is there. Realized this after wasting a day.