resgateio / resgate

A Realtime API Gateway used with NATS to build REST, real time, and RPC APIs, where all your clients are synchronized seamlessly.
https://resgate.io
MIT License
685 stars 67 forks source link

Incompatible with nats:latest (nats ^2.1.0) #200

Closed LucienBrule closed 3 years ago

LucienBrule commented 3 years ago

Expected Behaviour

As a user of resgate I am able to replicate the functionality of the jwt-authentication example

Actual Behaviour

The browser is not authenticated and gives the following error

 {"error":{"code":"system.accessDenied","message":"Access denied"},"id":3}

Steps to reproduce

Instrumentation:

  1. $ nats sub >

    • watches all nats messages being sent to the broker
  2. append --trace to Resgate docker run command

    Steps to reproduce:

  3. Bring up auth service (../jwt-authentication/authService.js) (yarn start)

  4. Comment out the two publish lines below

  5. Bring up this service (yarn run dev)

  6. Navigate to http://localhost:8084

  7. Login

  8. Go back

  9. Refresh the page

  10. Observe the terminal output of both services

    So the other service is the one handling these requests, it works as expected the browser displays hello world.

    Presumably we are doing the exact same thing in both services, as show by the terminal output...right?

    Let's make sure:

  11. Comment out the publish lines in the other service

  12. Uncomment the lines in this service

  13. Refresh the browser (do it twice, it doesn't always work first try)

  14. Observe how the request fails yet we have the "same" thing being sent as the other service.

    ¯_(ツ)_/¯

    ie:

    Original Service:

    [Auth] Received new message _INBOX.7Ap64yZ6OjkInVcCNbwmv2
    [Auth] Response 1:  {"token":{"foo":"bar","iat":1629071958}}
    [Auth] Response 2:  {"result":null}
    [Auth] Processed message
    [Example] Token is:  { foo: 'bar', iat: 1629071958 }

    This Service:

    [Auth 2.0] Received new message _INBOX.7Ap64yZ6OjkInVcCNbwmv2
    [Auth 2.0] Repsponse 1:  {"token":{"foo":"bar","iat":1629071958}}
    [Auth 2.0] Response 2:  {"result":null}
    [Auth 2.0] Processed message
    ... [Example] Token is:  null

    Yields:

    {"error":{"code":"system.accessDenied","message":"Access denied"},"id":3}

Speculation

I'm either doing something wildly wrong, because I swear the implementation is the same, or there's a version incompatibility with the latest version of nats.

Perhaps it has something to do with the new string encoding that the nats client uses?

I'm willing to make a PR, I just need some guidance.

I submitted a PR and would like to contribute an example that works with the newest client. I think this project is awesome and it would solve a lot of pain points on our team if I could resolve this issue.

LucienBrule commented 3 years ago

PR https://github.com/resgateio/resgate/pull/199

jirenius commented 3 years ago

@LucienBrule Thanks for bringing this to my attention. I will immediately have a look at it.

jirenius commented 3 years ago

@LucienBrule I tried out your version, but unfortunately I couldn't get it to compile.

But I made a working example using nats 2.1.0 in a feature branch: https://github.com/resgateio/resgate/tree/feature/gh-200-jwt-authentication-nats-2-example/examples/jwt-authentication-nats-2

It seems quite compatible :) . The issue might instead be some bug in your example.

Converting examples to nats 2.x

The purpose of the examples is to show different concepts in working action; not at all to show any best practices. And while using nats 2.x is a better practice when writing node.js services, the example gets a bit more complex (async vs sync).

I guess I should upgrade all examples eventually, but for now I think I'll leave them with nats 1.x for the sake of simplicity.

LucienBrule commented 3 years ago

Huh, that's so odd. Sorry about the project not being able to compile swear I tried a clean install before I pushed it. My bad.

I appreciate you checking it out and thank you for confirming compatibility in the feature branch I'll check it out.

jirenius commented 3 years ago

@LucienBrule Might be me not being too familiar with TypeScript. But I tinkered a little to get your version to work:

The tsconfig.json refers to a non-existent file. I commented it out:

// "extends": "../../tsconfig.build.json",

The file index.ts is empty, so I added the line:

export {}

In auth.ts, the lines sending the token event and the response was commented out, so I uncommented them:

nats.publish(connectionID,tokenPayload)
// ... //
nats.publish(reply,okayPayload)

(Actually, I replaced nats.publish(reply.okayPayload) with message.respond(okayPayload). But that should make no difference.)

Then I ran my jwt-authentication example, but without the authService.js import, and instead used your auth.ts example. It all worked nicely :)

jirenius commented 3 years ago

I close this as I consider it answered. If you have more questions, you can create a new issue.