前端发起OAuth 2.0请求报错问题求助
问题描述
前端运行在localhost:3000,页面按钮需调用localhost:4000的后端接口/auth/google发起OAuth 2.0授权及后续回调。已验证OAuth控制器功能正常,但前端请求时报错。起初怀疑是CORS错误,查看网络日志后已排除该可能。
后端路由代码(index.js)
app.use(session({ secret:process.env.SECRET })); app.use(passport.initialize()); app.use(passport.session()); app.get('/',(req,res)=> { res.send('<a href="/auth/google">Auth With Google</a>') }) app.get('/auth/google', passport.authenticate('google') ) app.get('/auth/google/callback', passport.authenticate('google', { successRedirect:'http://localhost:3000/', failureRedirect:'/failure' }) )
Passport GoogleStrategy配置代码
passport.use(new GoogleStrategy({ clientID: GOOGLE_CLIENT_ID, clientSecret: GOOGLE_CLIENT_SECRET, callbackURL: "http://localhost:4000/auth/google/callback", scope: [ 'https://www.googleapis.com/auth/youtube', // Required to access YouTube data 'https://www.googleapis.com/auth/userinfo.profile', // Optional: access to user's profile ], passReqToCallback : true }, async function(request, accessToken, refreshToken, profile, done) { const response = await user.create({ googleId: profile.id, accessToken:accessToken }); return done(null,response); } ));
前端React代码
function App() { // Function to start the OAuth 2.0 authorization process const handleAuthClick = async () => { // Send a request to your Express.js backend to initiate the OAuth flow try { const response = fetch('http://localhost:4000/auth/google'); // const response = await axios.get("/auth/google"); // Tried Both Ways } catch (error) { console.error('Error initiating OAuth flow:', error); } }; return ( <div className='App flex flex-col gap-4'> <h1>Your App</h1> <button onClick={handleAuthClick}>Authorize YouTube Access</button> </div> ); }
解决方案
核心问题是用异步请求(fetch/axios)调用/auth/google接口的方式错误。Passport的Google OAuth认证流程需要触发浏览器跳转到Google的授权页面,而异步请求无法触发浏览器的页面重定向,因此会报错。
修复方式很简单,直接让按钮触发页面跳转即可,有两种实现方式:
方式1:修改按钮点击逻辑
将异步请求替换为直接跳转后端认证接口:
function App() { const handleAuthClick = () => { // 直接跳转到后端的OAuth发起地址 window.location.href = 'http://localhost:4000/auth/google'; }; return ( <div className='App flex flex-col gap-4'> <h1>Your App</h1> <button onClick={handleAuthClick}>Authorize YouTube Access</button> </div> ); }
方式2:用a标签伪装成按钮
如果想要避免写JS逻辑,可以直接用<a>标签指向后端接口,再通过CSS把它改成按钮样式:
function App() { return ( <div className='App flex flex-col gap-4'> <h1>Your App</h1> <a href="http://localhost:4000/auth/google" className="button-style"> Authorize YouTube Access </a> </div> ); }
补充说明:后端的/auth/google接口本身就是用来触发重定向到Google授权页的,不需要前端处理它的响应。整个OAuth流程会在浏览器端完成跳转,认证成功后会自动根据后端配置跳回localhost:3000。
内容的提问来源于stack exchange,提问作者Harsh Sharma
相关产品推荐
相关产品推荐

