reactive-interaction-gateway icon indicating copy to clipboard operation
reactive-interaction-gateway copied to clipboard

Unable to validate JWT via external service

Open patrickmedina opened this issue 3 years ago • 4 comments

Summary and context

The external JWT validator service successfully receives the POST request and returns 200 OK but RIG always returns "Invalid Signature".

How to reproduce

When I run RIG with these settings:

  • External service is running on port 3000 on host machine and is accessible from docker containers.

  • External service immediately returns 200 OK for testing and doesn't actually validates the JWT.

  • RIG Config values:

SUBSCRIPTION_CHECK=http://host.docker.internal:3000

..and set up clients and services like this:

  • Initiate Websocket connection:

$ wscat -c ws://localhost:4000/_rig/v1/connection/ws

  • Subscription request:

$ curl -X PUT -H "Content-Type: application/json" -d '{"subscriptions":[{"eventType":"position","oneOf":[{"userType":"admin"}]}]}' -H "Authorization: Bearer jwt_token" "http://localhost:4000/_rig/v1/connection/ws/0B7ilUe9imppbOep5E9Gw_KD8ZR7Jal4HK2ZyG0cZXO2VBwxAxT8ZIUGA_YORriC7I3nppuaNfv48PQzbtQ=/subscriptions"

..I see the following error and/or log output:

  • Subscription response:

cannot accept subscription request: invalid authorization header: could not decode JWT: Invalid signature

  • JWT service received request from RIG:

{ method: 'POST', url: '/', header: { authorization: 'Bearer jwt_token', host: 'host.docker.internal:3000', 'user-agent': 'hackney/1.16.0', 'content-type': 'application/json', 'content-length': '75' } }

  • RIG logs:

rig-dev | 16:15:06.145 module=Phoenix.Logger request_id=Fn_mwLBz4wK9hIAAAABB [debug] Processing with RigInboundGatewayWeb.V1.SubscriptionController.set_subscriptions/2 rig-dev | Parameters: [UNFETCHED] rig-dev | Pipelines: [:api] rig-dev | 16:15:06.145 module=Plug.Logger request_id=Fn_mwLBz4wK9hIAAAABB [debug] PUT /_rig/v1/connection/ws/0B7ilUe9imppbOep5E9Gw_KD8ZR7Jal4HK2ZyG0cZXO2VBwxAxT8ZIUGA_YORriC7I3nppuaNfv48PQzbtQ=/subscriptions rig-dev | 16:15:06.149 module=RigInboundGatewayWeb.V1.SubscriptionController request_id=Fn_mwLBz4wK9hIAAAABB [warn] failed to associate to session: ["%RIG.JWT.DecodeError{cause: "Invalid signature"}"]

..but I really expected this:

  • Successful subscription:

{"subscriptions":[{"eventType":"position","oneOf":[{"userType":"admin"}]....

Versions (please complete the following information):**

  • Host OS: Docker on MacOS[MacBook Pro (16-inch, 2019)]
  • Frontend: curl
  • RIG version as shown on startup: Reactive Interaction Gateway 3.0.0-alpha.1 [[email protected], ERTS 11.1.8, OTP 23]

patrickmedina avatar May 17 '21 16:05 patrickmedina

Better to implement JWKS validation as alternative to external JWT validation service. I think JWKS hooks for Joken can be used for this.

patrickmedina avatar May 17 '21 16:05 patrickmedina

@patrickmedina should be fixed with #378 - can you confirm?

kevinbader avatar May 23 '21 20:05 kevinbader

@kevinbader Thank you for the fix. It is now working for manual subscriptions, it is now validating against the configured external service via SUBSCRIPTION_CHECK envvar.

Can we have this work as well on automatic subscriptions via JWT claims? This will be a great help as well to reduce the API calls and rely on the JWT claims for the subscriptions on initial connection.

Currently when passing JWT during websocket connection, it still checks for internal JWT configuration instead of validating against an external service.

Request:

wscat -c ws://localhost:4000/_rig/v1/connection/ws\?jwt\=<jwt>

or

wscat -c ws://localhost:4000/_rig/v1/connection/ws -H "Authorization: Bearer <jwt>"

RIG Logs:

rig-dev    | 06:56:40.202 module=RigInboundGatewayWeb.V1.Websocket [debug] Closing WebSocket connection (#PID<0.3013.0>, reason=:remote)
rig-dev    | 06:56:53.361 module=RigInboundGatewayWeb.ConnectionInit [debug] new WS connection (pid=#PID<0.3347.0>, params=%RIG.AuthorizationCheck.Request{auth_info: %{auth_header: "Bearer <jwt>", auth_tokens: [{"bearer", "<jwt>"}]}, body: nil, content_type: "application/json; charset=utf-8", query_params: ""})
rig-dev    | 06:56:53.361 module=RigInboundGatewayWeb.ConnectionInit [warn] Cannot accept WS connection #PID<0.3347.0>: could not parse subscriptions: could not decode JWT: Invalid signature
rig-dev    | 06:56:53.361 module=RigInboundGatewayWeb.V1.Websocket [warn] websocket error: "could not parse subscriptions: could not decode JWT: Invalid signature"
rig-dev    | 06:56:53.362 module=RigInboundGatewayWeb.V1.Websocket [debug] Closing WebSocket connection (#PID<0.3347.0>, reason=:stop)

patrickmedina avatar May 24 '21 07:05 patrickmedina

Ah, I see. I need to redesign this a bit to only allow invalid JWTs in case SUBSCRIPTION_CHECK isn't set to jwt_validation and generally make this more consistent. It'll take me a few days to do it though.

kevinbader avatar May 24 '21 22:05 kevinbader