jaredhanson / passport-oauth2

OAuth 2.0 authentication strategy for Passport and Node.js.
https://www.passportjs.org/packages/passport-oauth2/?utm_source=github&utm_medium=referral&utm_campaign=passport-oauth2&utm_content=about
MIT License
604 stars 343 forks source link

InternalOAuthError: Failed to obtain access token Error: write EPROTO 31636 #110

Open sauravpandit opened 5 years ago

sauravpandit commented 5 years ago

Hi, I was trying use this library for authentication using our internal oAuthprovider. They are using openId connect as oAuth provider. I am changing the original URL and client id client secrete for security purpose. Here is the issue I am facing. Step 1: Click on http://localhost:3000/login It will display Log In with IdP. Status:Passd Step 2: Click on "Log In with IdP" http://localhost:3000/login/idp will redirect user to authorization site. Status:Passed Step 3: User will provide credential at authorization site and then site will ask user for permission. Clicking continue at authorization site should redirect request to callback url. Status:Passed Step 4: Application should read token from redirected URL. Status: Failed

At first I was getting

InternalOAuthError: Failed to obtain access token at OAuth2Strategy._createOAuthError (C:\data\CODE\Node\express-4.x-openidconnect-example-master\node_modules\passport-oauth2\lib\strategy.js:408:17) at C:\data\CODE\Node\express-4.x-openidconnect-example-master\node_modules\passport-oauth2\lib\strategy.js:175:45 at C:\data\CODE\Node\express-4.x-openidconnect-example-master\node_modules\oauth\lib\oauth2.js:196:18 at ClientRequest. (C:\data\CODE\Node\express-4.x-openidconnect-example-master\node_modules\oauth\lib\oauth2.js:166:5) at ClientRequest.emit (events.js:189:13) at TLSSocket.socketErrorListener (_http_client.js:392:9) at TLSSocket.emit (events.js:189:13) at onwriteError (_stream_writable.js:431:12) at onwrite (_stream_writable.js:456:5) at _destroy (internal/streams/destroy.js:40:7)

After debugging application I understand that It is the following error which is causing the above error

{ Error: write EPROTO 83964:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:openssl\ssl\record\rec_layer_s3.c:1407:SSL alert number 40

at WriteWrap.afterWrite [as oncomplete] (net.js:782:14) errno: 'EPROTO', code: 'EPROTO', syscall: 'write' }

My application is running at localhost and authorization site is at https. My best guess is It is happening because of http to https communication but I am not sure of that because most example in internet is are created in the same way I did. They are also using http to https communication.

It will be great if anyone can provide some solution to this issue.
Please let me know if you need more information regarding this.

I have created a small example like below `var express = require('express'); var passport = require('passport'); var OAuth2Strategy = require('passport-oauth2').Strategy; passport.use(new OAuth2Strategy({ authorizationURL: 'https://mysite.provider.com/oauth2/authorize', tokenURL: 'https://mysite.provider.com/token', clientID: 'Test7QCfQFiUca', clientSecret: 'TestwfYpNhu4QYDWAa', callbackURL: "http://localhost:3000/callback" }, function(accessToken, refreshToken, profile, cb) { User.findOrCreate({ exampleId: profile.id }, function (err, user) { return cb(err, user); }); } ));

passport.serializeUser(function(user, done) { done(null, user); });

passport.deserializeUser(function(obj, done) { done(null, obj); });

// Create a new Express application. var app = express();

// Configure view engine to render EJS templates. app.set('views', __dirname + '/views'); app.set('view engine', 'ejs');

// Use application-level middleware for common functionality, including // logging, parsing, and session handling. app.use(require('morgan')('combined')); app.use(require('cookie-parser')()); app.use(require('body-parser').urlencoded({ extended: true })); app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));

// Initialize Passport and restore authentication state, if any, from the // session. app.use(passport.initialize()); app.use(passport.session());

// Define routes. app.get('/', function(req, res) { res.render('home', { user: req.user }); });

app.get('/login', function(req, res){ res.render('login'); });

app.get('/login/idp', passport.authenticate('oauth2'));

app.get('/callback', passport.authenticate('oauth2', { failureRedirect: '/login' }), function(req, res) { res.redirect('/'); });

app.get('/profile', require('connect-ensure-login').ensureLoggedIn(), function(req, res){ res.render('profile', { user: req.user }); });

app.listen(3000); `

sauravpandit commented 5 years ago

In order to fix the issue have set proxy and https_proxy using npm config but I am still getting the same error. Note: After user clicking continue at authorization site(providing permission) it calling my redirect url with code like below http://localhost:3000/callback?code=d6d8da87-0676-3b51-bb0e-5946ff50a847 But application is still showing me the same error. I am using "passport-oauth2": "^1.5.0" and node v10.15.1

sauravpandit commented 5 years ago

Hi here is Node js version details { http_parser: '2.8.0', node: '10.15.1', v8: '6.8.275.32-node.12', uv: '1.23.2', zlib: '1.2.11', ares: '1.15.0', modules: '64', nghttp2: '1.34.0', napi: '3', openssl: '1.1.0j', icu: '62.1', unicode: '11.0', cldr: '33.1', tz: '2018e' }

Can I get some some help on this? I am completely stuck on this.

danyxudong commented 5 years ago

Hi Sauravpandit, I have the same problem as you. so long time, have you fix this problem? if yes, could you share with me?

danyxudong commented 5 years ago

Hi Sauravpandit,

I searched google a while, found a solution, and my test is ok, please check it in the below.

1st, please find your proxy on the internet explorer. My sample is http://192.168.23.4:999;

2nd, install "https-proxy-agent" node package in your project folder;

$ npm install https-proxy-agent

3rd, write the code as below;

const HttpsProxyAgent = require('https-proxy-agent');

const gStrategy = new GoogleStrategy({
    clientID: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    callbackURL: "http://localhost:3000/auth/google/secrets",
    userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
  },
  function(accessToken, refreshToken, profile, cb) {
    console.log(profile);
    User.findOrCreate({ googleId: profile.id }, function (err, user) {
      return cb(err, user);
    });
  }
);
const agent = new HttpsProxyAgent(process.env.HTTP_PROXY || "http://192.168.23.4:999");
gStrategy._oauth2.setAgent(agent);

passport.use(gStrategy);

Wish my solution works for you.

Reference:

  1. Github: https://github.com/jaredhanson/passport-oauth2/issues/59

  2. NPM: https://www.npmjs.com/package/https-proxy-agent

saran2828 commented 4 years ago

hi All,

We are facing similar issue with passport-idaas-openidconnect . We dont have "_oauth2" exposed for setAgent method. Is there any other alternative way to set the proxy agent.

Can I get some some help on this? I am completely stuck on this.