hapijs / nes

WebSocket adapter plugin for hapi routes
Other
502 stars 87 forks source link

nes fails to verify credentials with hapi-auth-jwt2 customVerify function #292

Closed abillingsley closed 4 years ago

abillingsley commented 4 years ago

Disclaimer: The following issue may actually be an issue with the hapi-auth-jwt2 which revealed when using nes.

I have a hapi server that authenticates routes using hapi-auth-jwt2 by default hapi-auth-jwt2 will verify JWT tokens using a public key or secret, however, hapi-auth-jwt2 also supports adding your own custom verify function. My configuration relies on hapi-auth-jwt2 and a customVerify function.

My plugin configuration takes all the defaults

{
    plugin: require("nes"),
    options: {
    },
  }

The options passed to the hapi-auth-jwt2 is something like

{
      verify: async (decoded: IDecodedToken, request: Request) => {
         //custom code to verify auth token
      },
      tokenType: "bearer",
      complete: true,
    };
  }

the client provides the JWT token as a bearer token

const websocket = new Websocket.Client(...);
websocket.connect({ auth: { headers: { authorization: 'bearer ...'; } } });

When establishing the connection to nes the a hello message is sent as part of the protocol

{"type":"hello","version":"2","auth":{"headers":{"authorization":"bearer ..."}},"id":1}

while processing this message the internal route nes/auth is invoked which properly leverages the hapi-auth-jwt2 auth strategy and the custom verify method implemented when configuring that plugin as evidence by the successful response from the hello messgae

{"type":"hello","id":1,"heartbeat":{"interval":15000,"timeout":5000},"socket":"1568994069665:1339202c9140:134:k0sa3an6:10002"}

eventually while processing messages I think a ping the _verifyAuth method is called https://github.com/hapijs/nes/blob/master/lib/socket.js#L282

which invokes this.server.auth.verify https://github.com/hapijs/nes/blob/master/lib/socket.js#L624 which invokes a call to the hapi server to start the process of determining auth based on the configured strategies https://github.com/hapijs/hapi/blob/master/lib/auth.js#L100

under certain circumstances, the verify function will be invoked in the auth strategy (hapi-auth-jwt2) https://github.com/hapijs/hapi/blob/master/lib/auth.js#L120

when delegating off to the auth strategy for verification the following method is called within the hapi-auth-jwt2 library https://github.com/dwyl/hapi-auth-jwt2/blob/master/lib/index.js#L295

which is the default verify function and not the custom verify function defined. Eventually in my case, this results in

{"statusCode":403,"payload":{"error":"Forbidden","message":"Credential verification failed"},"type":"ping","id":4}

The interesting thing is some pings and message can be sent and verified but eventually, verification will fail.

The underlying error that is thrown by hapi.auth.verify is a JsonWebTokenError with the message secret or public key must be provided. This occurs because I am using a customVerify function which is not using a public key for verification.

hapi-auth-jwt2 should likely resolve this issue but it is curious to me that the hello message is successful and a few ping messages are successful before eventually failing with a 403. I would expect nes to fail immediately for the socket if authentication is invalid.

hueniverse commented 4 years ago

I am not sure why it would sometimes be able to reverify but it's probably not. In some cases verification is just not triggered. Either way the bug is in the plugin. It fails to take into account the custom verification step when verifying.

I think part of the problem is that the hapi-auth-jwt2 plugin config is very rich and tries to support every use case people came up with. The result is too many validation paths which is hard to keep consistent. I made different choices with my jwt pluging but that requires a hapi commercial support plan.

lock[bot] commented 4 years ago

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.