如何在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
相关产品推荐
相关产品推荐

