You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中自定义Google OAuth按钮并获取JWT令牌

问题

我在应用中使用@react-oauth/google包进行用户认证,后端需要凭据响应中的JWT令牌。该包仅在GoogleLogin组件或useGoogleOneTapLogin钩子的onSuccess回调中提供credentialsResponse。

目前我通过GoogleLogin组件实现功能(已在App.jsx中配置好GoogleOAuthProvider且可正常运行):

import {
  GoogleLogin,
  useGoogleLogin,
  useGoogleOneTapLogin,
} from "@react-oauth/google";

export const GoogleLoginButton = () => {
  const onGoogleSuccess = async (tokenResponse) => {
    try {
      const userData = jwtDecode(tokenResponse?.credential);

      if (isSignup) {
        // 后续会将JWT令牌发送给后端
        setGoogleRes({ ...userData, ...tokenResponse });
      } else {
        loginUser(userData, tokenResponse);
      }
    } catch (error) {
      setOpen(true);
      setToastData(ToastConstant.SOMETHING_WENT_WRONG);
      console.log("Google fetch error", { error });
    }
  };

  const onGoogleError = (error) => {
    setGoogleRes(null);
    setOpen(true);
    setToastData(ToastConstant.SOMETHING_WENT_WRONG);
  };

  return (
    <GoogleLogin
      onSuccess={onGoogleSuccess}
      onFailure={onGoogleError}
      text="continue_with"
      theme="outline"
      width="100%"
      containerProps={{
        style: {
          width: "100% !important",
        },
      }}
    />
  );
};

但我希望创建一个完全自定义的按钮,能匹配网站主题风格,自由定制UI和显示文本。多数自定义Google OAuth按钮的库已废弃,仅@react-oauth/google可用,请问如何实现自定义按钮且在onSuccess回调中获取JWT令牌?


解决方案

方法一:使用useGoogleLogin钩子自定义按钮

useGoogleLogin钩子可直接触发Google认证流程,让你完全控制按钮UI,同时在回调中获取JWT令牌:

import { useGoogleLogin } from "@react-oauth/google";
import jwtDecode from "jwt-decode";

export const CustomGoogleLoginButton = () => {
  const login = useGoogleLogin({
    onSuccess: async (tokenResponse) => {
      try {
        const userData = jwtDecode(tokenResponse?.credential);
        if (isSignup) {
          setGoogleRes({ ...userData, ...tokenResponse });
        } else {
          loginUser(userData, tokenResponse);
        }
      } catch (error) {
        setOpen(true);
        setToastData(ToastConstant.SOMETHING_WENT_WRONG);
        console.log("Google fetch error", { error });
      }
    },
    onError: () => {
      setGoogleRes(null);
      setOpen(true);
      setToastData(ToastConstant.SOMETHING_WENT_WRONG);
    },
    // 需设置以下参数以获取ID Token(JWT)
    scope: "openid email profile",
    responseType: "id_token",
  });

  return (
    <button 
      onClick={login}
      style={{
        padding: "12px 24px",
        backgroundColor: "#4285F4",
        color: "#fff",
        border: "none",
        borderRadius: "4px",
        cursor: "pointer",
        fontSize: "16px",
        display: "flex",
        alignItems: "center",
        gap: "8px",
        width: "100%",
      }}
    >
      {/* 可自定义图标与文本 */}
      <span>📧</span>
      用Google账号登录
    </button>
  );
};

方法二:隐藏官方GoogleLogin组件,用自定义按钮触发点击

若想保留官方组件的认证逻辑,仅替换UI,可将官方GoogleLogin组件隐藏,通过自定义按钮触发其点击事件:

import { useRef } from "react";
import { GoogleLogin } from "@react-oauth/google";
import jwtDecode from "jwt-decode";

export const CustomGoogleLoginButton = () => {
  const googleLoginRef = useRef(null);

  const onGoogleSuccess = async (tokenResponse) => {
    try {
      const userData = jwtDecode(tokenResponse?.credential);
      if (isSignup) {
        setGoogleRes({ ...userData, ...tokenResponse });
      } else {
        loginUser(userData, tokenResponse);
      }
    } catch (error) {
      setOpen(true);
      setToastData(ToastConstant.SOMETHING_WENT_WRONG);
      console.log("Google fetch error", { error });
    }
  };

  const onGoogleError = (error) => {
    setGoogleRes(null);
    setOpen(true);
    setToastData(ToastConstant.SOMETHING_WENT_WRONG);
  };

  return (
    <>
      {/* 自定义按钮 */}
      <button 
        onClick={() => googleLoginRef.current?.click()}
        style={{
          padding: "12px 24px",
          backgroundColor: "#fff",
          color: "#333",
          border: "1px solid #ddd",
          borderRadius: "4px",
          cursor: "pointer",
          fontSize: "16px",
          display: "flex",
          alignItems: "center",
          gap: "8px",
          width: "100%",
        }}
      >
        <span>📧</span>
        继续使用Google账号
      </button>
      {/* 隐藏官方组件 */}
      <div style={{ display: "none" }}>
        <GoogleLogin
          ref={googleLoginRef}
          onSuccess={onGoogleSuccess}
          onFailure={onGoogleError}
          text="continue_with"
        />
      </div>
    </>
  );
};

注意事项

  • 确保已在GoogleOAuthProvider中正确配置客户端ID
  • 使用useGoogleLogin时,需将responseType设为id_token才能获取JWT令牌
  • 自定义按钮的样式可根据网站主题完全调整,包括颜色、字体、图标等

内容的提问来源于stack exchange,提问作者B e e p

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:52:38