passport-google-oauth拉取用户资料失败报ECONNRESET错误
问题描述
基于MEANJS框架搭建的网站Google登录功能已稳定运行三年,未修改任何业务代码的情况下突然停止工作。功能可以正常跳转至Google授权同意页面,用户完成登录操作触发回调时报错。
相关代码
Passport Google OAuth 策略配置
/** * Module dependencies */ var passport = require('passport'), GoogleStrategy = require('passport-google-oauth').OAuth2Strategy, users = require('../../controllers/users.server.controller'); module.exports = function (config) { // Use google strategy passport.use(new GoogleStrategy({ clientID: config.google.clientID, clientSecret: config.google.clientSecret, callbackURL: config.google.callbackURL, passReqToCallback: true, scope: ['profile', 'email'] }, function (req, accessToken, refreshToken, profile, done) { // Set the provider data and include tokens var providerData = profile._json; providerData.accessToken = accessToken; providerData.refreshToken = refreshToken; // Create the user OAuth profile var providerUserProfile = { firstName: profile.name.givenName, lastName: profile.name.familyName, displayName: profile.displayName, email: profile.emails[0].value, username: profile.username, profileImageURL: (providerData.picture) ? providerData.picture : undefined, provider: 'google', providerIdentifierField: 'id', providerData: providerData }; // Save the user OAuth profile users.saveOAuthUserProfile(req, providerUserProfile, done); })); };
回调处理逻辑
passport.authenticate('google', {},function (err, user, info) { if (err) { console.log(err); return res.redirect('/authentication/signin?err=' + encodeURIComponent(errorHandler.getErrorMessage(err))); } if (!user) { return res.redirect('/authentication/signin'); } .....
报错日志
回调执行时返回Failed to fetch user profile错误,控制台打印的错误完整信息如下:
{ InternalOAuthError: Failed to fetch user profile at C:\Users\Administrator\Documents\printer\mean-printer\node_modules\passport-google-oauth20\lib\strategy.js:99:19 at ClientRequest.<anonymous> (C:\Users\Administrator\Documents\printer\mean-printer\node_modules\oauth\lib\oauth2.js :162:5) at emitOne (events.js:116:13) at ClientRequest.emit (events.js:211:7) at TLSSocket.socketErrorListener (_http_client.js:401:9) at emitOne (events.js:116:13) at TLSSocket.emit (events.js:211:7) at emitErrorNT (internal/streams/destroy.js:66:8) at _combinedTickCallback (internal/process/next_tick.js:139:11) at process._tickDomainCallback (internal/process/next_tick.js:219:9) name: 'InternalOAuthError', message: 'Failed to fetch user profile', oauthError: { Error: read ECONNRESET at TLSWrap.onread (net.js:622:25) errno: 'ECONNRESET', code: 'ECONNRESET', syscall: 'read' } }
故障根因分析
无代码改动下稳定运行三年的Google登录突发Failed to fetch user profile+ECONNRESET错误,核心原因按概率从高到低排序:
- 最常见原因:Google 已完全下线旧版Google+ 个人信息API。当前使用的老旧版本
passport-google-oauth包,默认拉取用户信息的接口是https://www.googleapis.com/plus/v1/people/me,该接口属于已关停的Google+服务,服务分批次下线过程中就会出现无代码改动下功能突然失效的情况,连接直接被重置符合接口关停时的返回特征。 - 网络链路异常:服务器出口网络规则变更、访问Google API的链路被中间设备拦截重置,会直接抛出
ECONNRESET错误。 - 运行环境兼容问题:如果近期有过服务器系统升级、Node.js版本升级、依赖包隐式重装,老版本OAuth包和新的TLS/OpenSSL环境不兼容,也会导致握手失败连接重置。
可落地修复方案
按优先级依次尝试:
- 临时快速修复(无需升级依赖)
在现有Google策略配置中新增userProfileURL参数,手动指定为Google当前在用的公开用户信息接口,覆盖默认的已废弃接口:
passport.use(new GoogleStrategy({ clientID: config.google.clientID, clientSecret: config.google.clientSecret, callbackURL: config.google.callbackURL, passReqToCallback: true, scope: ['profile', 'email'], userProfileURL: 'https://www.googleapis.com/oauth2/v3/userinfo' // 新增该行 }, // 原有回调逻辑无需任何修改
改完重启服务即可测试,90%以上的同类突发故障改完就能恢复。
- 长期稳定修复
替换为官方持续维护的新版OAuth策略包,彻底解决旧包接口不更新的问题:- 先卸载旧包,安装新版包:
npm uninstall passport-google-oauth npm install passport-google-oauth20
- 修改策略引入代码,把原有的:
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy
替换为:
GoogleStrategy = require('passport-google-oauth20').Strategy
其余配置、回调逻辑不需要调整,重启服务即可。
- 网络/环境排查
如果上述修改后仍报错,先在部署服务器上直接执行命令测试接口连通性:
curl -v https://www.googleapis.com/oauth2/v3/userinfo
如果返回连接重置,排查服务器出口防火墙、路由规则,确保到Google API的链路正常。如果连通性正常但仍报错,回退Node.js版本到之前稳定运行时的LTS版本,或删除node_modules和package-lock.json重新安装依赖,解决隐式版本兼容问题。
内容的提问来源于stack exchange,提问作者Dor Moshkovitz
相关产品推荐
相关产品推荐

