Question: Passport JWT auth in unit test - socket hang up

Question

Passport JWT auth in unit test - socket hang up

Answers 1
Added at 2016-12-30 16:12
Tags
Question

I'm having an emotional time trying to test protected routes that use passport's JWT strategy, with Authorization header.

I've tried axios, supertest, superagent and I get the same error - 'socket hang up':

Error: socket hang up
at createHangUpError (_http_client.js:253:15)
at Socket.socketOnEnd (_http_client.js:345:23)
at emitNone (events.js:91:20)
at Socket.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickDomainCallback (internal/process/next_tick.js:122:9) code: 'ECONNRESET', response: undefined }

This works perfectly in dev environment, this only happens in test environment - unit tests or dev env pointing to test DB/users.

I know this error means that the connection was closed by a crash on the server or a syntax error, however there are no syntax errors. The endpoint doesn't get past the passport auth:

passport.authenticate('jwt'...

Why? How can this be resolved?

The endpoint:

router.route('/private')
  .get(
    passport.authenticate('jwt', { session: false }), (req, res, next) => {
      res.json({ allTheThings: true });
  })

The test:

describe('GET /api/private', () => {
  it('should work', () => {
    const USER_JWT_VALID = 'JWT asdf.....';

    let instance = axios.create();
    instance.defaults.headers.common['Authorization'] = USER_JWT_VALID;

    return instance.get('http://localhost:3000/api/private')
      .then((response) => {
        expect(response.data).to.be.an('object'); // response.data undefined
      }).catch((error) => {
        console.log('err ', error); //socket hang up
      });
  });
});

If I remove the passport.authenticate and simply send a json response, it works as expected.

The logs show that the request is sent with a correct JWT in Authorization header.

RE comments

I have a different DB/users for dev and test. Using the test DB in dev, i'm able to replicate the issue seen in the unit tests. If I exclude an authorization header, as expected I get an 'Unauthorized' response (from a token check function).

As soon as I add an authorization header with JWT, I don't get any response at all :(

Further debugging

It seems that my api is no longer able to do any GET requests, in test environment, if there is an authorization header. With no header, all works fine. I suspect this is to do with some recent dependency updates.

Answers to

Passport JWT auth in unit test - socket hang up

nr: #1 dodano: 2017-01-01 11:01

After creating a brand new user for the test environment and using this in the unit tests, everything works as expected. GET requests with the users's JWT in Authorization header work perfectly.

It seems that the user being used for authentication, in the test environment (from mongo db), was somehow using an invalid JWT. Maybe to do with the way the JWT is constructed based on the user schema.

I don't know why or how this happened (early build stage). Unable to replicate now.

My unit tests were doing the following:

1) POST to authentication endpoint to get JWT token (from user email and password)

2) GET private auth only endpoint with that JWT.

On the private GET, passport.authenticate('jwt' .... was just not working at all and hence, no requests or responses.

I cannot see any other reason why this would not work other than an invalid JWT.

I have learnt from this that if you have failing unit tests with authentication involved, rule out old/new users and work from that.

Source Show
◀ Wstecz