Reputation: 1163
While developing the last example of a node.js's introductory book (an express.js application using authentication strategy by Google OpenID), after replacing the passport-google
package (which got obsolete on April 20th, 2015) with passport-google-oauth2
package (authentication strategy by Google OAuth 2.0) and having followed the indications at its documentation's page and an example here; I got the below error after selecting my Google+ account, which was thrown by the oath2.js
module, concretely calling this._oauth2.get("https://www.googleapis.com/plus/v1/people/me",...)
within userProfile(accessToken, done)
method. The related source code and module dependencies are below.
What could be the root of the problem?
The concrete error is:
InternalOAuthError: failed to fetch user profile
at <...>\web-app\b4\node_modules\passport-google-oauth2\lib\oauth2.js:92:28
at passBackControl (<...>\web-app\b4\node_modules\passport-google-oauth2\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:124:9)
at IncomingMessage.<anonymous> (<...>\web-app\b4\node_modules\passport-google-oauth2\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:143:7)
at IncomingMessage.emit (events.js:129:20)
at _stream_readable.js:908:16
at process._tickCallback (node.js:355:11)
The related application's code is:
passport = require('passport'),
//...
GoogleStrategy = require('passport-google-oauth2').Strategy; // #passport-google-oauth2
//...
/***** #passport-google-oauth2 vv *****/
passport.use(new GoogleStrategy({
clientID: "a_specific_value",
clientSecret: "another_specific_value",
callbackURL: "http://127.0.0.1:3000/auth/google/callback",
passReqToCallback:true
},
function(request, accessToken, refreshToken, profile, done) {
profile.identifier=profile.id;
return done(null, profile);
}
));
/***** #passport-google-oauth2 ^^ *****/
//...
/***** #passport-google-oauth2 vv *****/
app.get('/auth/google',
passport.authenticate('google', { successRedirect: '/',scope:
[ 'https://www.googleapis.com/auth/userinfo.email']})
);
app.get( '/auth/google/callback',
passport.authenticate( 'google', {
successRedirect: '/',
failureRedirect: '/'
}));
/***** #passport-google-oauth2 ^^ *****/
The application has the following dependencies:
[email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ └─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] └─┬ [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] └── [email protected]
Upvotes: 22
Views: 16742
Reputation: 185
In my case, the error "Failed to fetch user profile"
was caused by a bug in the grand-parent library node-oauth
. Specifically, it was a double callback handling.
https://github.com/jaredhanson/passport-google-oauth2/issues/87
These libraries passport-google-oauth2
, node-oauth
are very old and not maintained well. And I didn't want to play with my own forks on GitHub. I quickly fixed it with a package patch
approach.
https://dev.to/zhnedyalkow/the-easiest-way-to-patch-your-npm-package-4ece
How I applied a patch for the node-oauth
library with patch-package
:
Install patch-package
library.
Patch node_modules/oauth/lib/oauth2.js
with the code:
request.on('error', function(e) {
// `www.googleapis.com` does `ECONNRESET` just after data is received in `passBackControl`
// this prevents the callback from being called twice, first in passBackControl and second time in here
// see also NodeJS Stream documentation: "The 'error' event may be emitted by a Readable implementation at any time"
if(!callbackCalled) {
callbackCalled= true;
callback(e);
}
});
npx patch-package node-oauth
.Upvotes: 0
Reputation: 850
This error is also thrown when logging in to an unpublished OAuth app with a user which is not in the Test Users
list (under OAuth consent screen
in Google's project console).
Upvotes: 0
Reputation: 166
When I change my package from passport-google-oauth
to passport-google-oauth20
, everything start to work properly.
Upvotes: 0
Reputation: 11
After some research, the root cause of the issue in my case was that I initially used
userProfileURL:"https://googleapis.com/oauth2/v3/userinfo" (WRONG)
instead of using
userProfileURL:"https://**www**.googleapis.com/oauth2/v3/userinfo"
Upvotes: 1
Reputation: 345
I was also facing the same issue !
Solution: Inside of
passport.use(new GoogleStrategy({
clientID: "a_specific_value",
clientSecret: "another_specific_value",
callbackURL: "http://127.0.0.1:3000/auth/google/callback",
passReqToCallback:true,
*********************************
},
On the stared line add this link "https://www.googleapis.com/oauth2/v3/userinfo" Final code will be as shown below passport.use(new GoogleStrategy({ clientID: GOOGLE_CLIENT_ID, clientSecret:.GOOGLE_CLIENT_SECRET, callbackURL: "http://localhost:3000/auth/google/secrets", passReqToCallback:true, userProfileURL:"https://www.googleapis.com/oauth2/v3/userinfo" }, This hope solves the problem !
Upvotes: -1
Reputation: 671
I found the same error and I solved it doing this:
In package.json, change "passport" value to "^0.4.0" and "passport-google-oauth" to "^2.0.0". Run "npm install" again.
Upvotes: 1
Reputation: 1104
I'm using Google OAuth 2.0 Playground and in my case the reason for this error was that my token has simply expired. Refreshing it in Playground resolved the issue.
Upvotes: 1
Reputation: 15222
The scope
you are using is deprecated now :
passport.authenticate('google', { successRedirect: '/',scope:
[ 'https://www.googleapis.com/auth/userinfo.email']})
);
Instead, we must use this one:
passport.authenticate('google', { successRedirect: '/',scope:
['email']
}));
You can also get the profile scope
:
passport.authenticate('google', { successRedirect: '/',scope:
[ 'email', 'profile' ]
}));
Upvotes: 7
Reputation: 1163
I just fortunately found a similar issue at
jaredhanson/passport-google-oauth, which gave me the idea to go to the Google's project console and simply enable the Google+ API
, which was "turned off" (oh me!!, naive developer of his first application based on Google+). That was the root of the problem. I tried again and the oauth2
started receiving profiles correctly.
Upvotes: 58