reactjs-social-login icon indicating copy to clipboard operation
reactjs-social-login copied to clipboard

Google Login i need idToken

Open tarangshah19 opened this issue 2 years ago • 6 comments

Describe the bug From Google Login i need idToken but not able to get how can i get that?

<LoginSocialGoogle client_id="373861975505-853d8bvtichuiltu546rhsrrjlq3al15.apps.googleusercontent.com" typeResponse="idToken" scope="openid profile email" ux_mode="popup" onResolve={({ provider, data }) => { const login = 'Google'; auth.login({ provider, data, login }, () => {}); }} onReject={err => { // eslint-disable-next-line no-console console.log(err); }} > <Button variant="contained" startIcon={<Icon icon="mdi:google" />} className="mb-2 socialBTN" id="Google" > Login with Google </Button> </LoginSocialGoogle>

tarangshah19 avatar Dec 04 '23 06:12 tarangshah19

You probably need an access token. Which is in the data on onResolve

marko-birdbuddy avatar Dec 07 '23 08:12 marko-birdbuddy

I managed to get this (google with this lib) working without any issues.

marko-birdbuddy avatar Dec 11 '23 09:12 marko-birdbuddy

@marko-birdbuddy Could you explain more about how you got this to work, I believe I'm having the same problem.

Frontend

import {loginApi, loginGoogleApi} from "../api/apiAuth";
import {getAnonymousKey, loginUser} from "../userAuth";
import {LoginSocialGoogle} from "reactjs-social-login";
import {GoogleLoginButton} from "react-social-login-buttons";

const responseGoogle = async (response) => {
    if (!response['access_token']) {
        alert('Unknown Google authentication error - try again or try alternative login.');
        console.log(response);
        return
    }
    try {
        const ret = await loginGoogleApi(response);
        loginUser(ret.data);
        window.location = '/';
    } catch (e) {
        setSuccess("Log in Failed!");
        console.log(e);
    }
}

return (
    <LoginSocialGoogle
        client_id="my-client-id.apps.googleusercontent.com"
        onResolve={({ provider, data }) => {
            console.log(provider);
            console.log(data);
            void responseGoogle(data);
        }}
        onReject={err => {
            console.log(err);
        }}
    >
        <GoogleLoginButton />
    </LoginSocialGoogle>

Backend

from google.auth.transport import requests
from google.oauth2 import id_token

@api_auth.route('/loginGoogle', methods=['POST'])
def login_google():
    data = request.get_json()

    try:
        id_info = id_token.verify_oauth2_token(data['access_token'], requests.Request(), GOOGLE_CLIENT_ID)
        email = id_info['email']

The above doesn't work, as OP said, I think you need the "id_token" and there's suppose to be some way of deriving one from the other.

More broadly though, is it a good idea to use google.oauth2 with this library, or is there a better solution for backend verification of tokens for most login providers just like reactjs-social-login? I tried asking this question on StackOverflow twice, and both times the moderators blocked it because that would invite an "opinionated response". sigh

occultus73 avatar Feb 17 '24 11:02 occultus73

Okay, I looked at the source code and saw that you can explicitly set a "typeResponse" to equal "idToken" where the default would otherwise be "accessToken". So this:

<LoginSocialGoogle
    client_id="my-client-id.apps.googleusercontent.com"
    onResolve={({ provider, data }) => {
        console.log(provider);
        console.log(data);
        void responseGoogle(data);
    }}
    onReject={err => {
        console.log(err);
    }}
    typeResponse="idToken"
>
    <GoogleLoginButton />
</LoginSocialGoogle>                   

...works fine - where data has the field "credential" instead of "access_token" - just like with @react-oauth/google.

occultus73 avatar Feb 17 '24 12:02 occultus73

Is this solution still working? I am receiving below error when trying to display login popup, using OP example.

[GSI_LOGGER]: FedCM get() rejects with AbortError: signal is aborted without reason

After removing typeResponse="idToken" popup opens and I can login, but I end with accessToken instead idToken.

piotr-ponikowski-source avatar Apr 12 '24 07:04 piotr-ponikowski-source

import React from 'react'; import { GoogleOAuthProvider, useGoogleLogin } from '@react-oauth/google'; import { Icon } from '@iconify/react/dist/iconify.js'; import { Button } from '@/components/ui/button'; import { ssoComponentString } from '@/constants/string-constants/SsoComponentString'; import useSSOApi from '../SsoApi';

const clientId = import.meta.env.VITE_REACT_APP_GOOGLE_CLIENT_ID;

const GoogleLoginButton: React.FC = () => { const { exchangeAuthCodeForTokens} = useSSOApi();

const googleLogin = useGoogleLogin({ flow: "auth-code", onSuccess: async (codeResponse) => { await exchangeAuthCodeForTokens(codeResponse.code); }, onError: (errorResponse) => console.error("Google Login Error:", errorResponse), scope: "openid email profile", }); return ( <Button variant="outline" type="button" data-testid="google-login-button" onClick={() => googleLogin()} > {' '} <Icon icon="devicon:google" /> {ssoComponentString.LoginButton.googleLogin} </Button> ); };

const GoogleLogin: React.FC = () => ( <GoogleOAuthProvider clientId={clientId}> <GoogleLoginButton /> </GoogleOAuthProvider> );

export default GoogleLogin;

import { useState } from 'react';

const useSSOApi = () => { const [loading, setLoading] = useState(false); const [error, setError] = useState<null | string>(null); const [tokens, setTokens] = useState(null);

const exchangeAuthCodeForTokens = async (code:string) => {
    setLoading(true);
    setError(null);
    try {
        const response = await fetch("https://oauth2.googleapis.com/token", {
            method: "POST",
            headers: { "Content-Type": "application/x-www-form-urlencoded" },
            body: new URLSearchParams({
                code,
                client_id: import.meta.env.VITE_REACT_APP_GOOGLE_CLIENT_ID,
                client_secret: import.meta.env.VITE_REACT_APP_GOOGLE_CLIENT_SECRET,
                redirect_uri: "http://localhost:5173",
                grant_type: "authorization_code",
            }),
        });
        const data = await response.json();
        if (!response.ok) throw new Error(data.error || "Failed to fetch tokens");
        
        setTokens(data);
    } catch (err) {
        setError(err instanceof Error ? err.message : "An unknown error occurred");
    } finally {
        setLoading(false);
    }
};
return { exchangeAuthCodeForTokens, tokens, loading, error };

};

export default useSSOApi;

it will fixed your id token issue

Ghanshyam007-rao avatar Mar 06 '25 12:03 Ghanshyam007-rao