antonis
antonis

Reputation: 133

Pass JWT to rabbitmq over websockets

This is my current RabbitMQ / Stomp setup which works fine with username and password authentication.

My end goal is to pass a JWT instead of username and password. I already have access to the token on the front-end and I do not want to conduct a UAA server. I have added this plugin to RabbitMQ and tried doing what step 3 of the Authorization flow says with no luck.

Client passes the token as password when connecting to a RabbitMQ node. The username field is ignored.

I get the following error:

<<< ERROR
content-length:16
version:1.0,1.1,1.2
content-type:text/plain
message:Processing error
content-length:16

Edit

Another observation is that after adding "Authorization: Bearer" in front of the token I get the a new error.

<<< ERROR
content-length:33
version:1.0,1.1,1.2
content-type:text/plain
message:Bad CONNECT
content-length:33

Access refused for user 'rabbit'

RabbitMQ Setup

Docker

FROM rabbitmq

RUN rabbitmq-plugins enable --offline rabbitmq_management
RUN rabbitmq-plugins enable --offline rabbitmq_stomp
RUN rabbitmq-plugins enable --offline rabbitmq_web_stomp
RUN rabbitmq-plugins enable --offline rabbitmq_auth_backend_oauth2

COPY ./advanced.config /etc/rabbitmq/advanced.config
COPY ./rabbitmq.conf /etc/rabbitmq/rabbitmq.conf

EXPOSE 15671 15672 15674 61613

advanced.config

[
  {rabbit, [
    {default_user, <<"admin">>},
    {default_pass, <<"guest">>},
    {auth_backends, [rabbit_auth_backend_oauth2, rabbit_auth_backend_internal]}
  ]},
  {rabbitmq_management, [
    {enable_uaa, false}
  ]},
  {rabbitmq_auth_backend_oauth2, [
    {resource_server_id, <<"rabbitmq">>},
    {key_config, [
      {default_key, <<"key-1">>},
      {signing_keys,
        #{<<"key-1">> => {pem, <<"-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAr8xZBLjW7yMZJobc/IFo
6New9jlCvSx8I6aSBrU+EU+TN6iXF13Tqqp62L/TWlTrYlErsu2yvLknhN4VU7qX
g38/2wZn9/kKFYCkeaDe3lDxl+4rNGq1TSEXCzndIDfVzgxZvKZ0Vt5+mvr1cxR7
7V6MFcJvIHMv4MdIqAUwABFFHvonp56yzh7g/UsAk6XlaqhoZQ1NrPyWpG6YgHwg
hFibyh0ZI3gD7H0UshpR9VVPLTgrAUnf3qWMpEXKO2ePmrTVwwDpL25n5DdhaBz6
e+YSonTT7KigxeklRPrKc7km29l0frml+8jOsQsx7L2WCD/HqR6J5iVDZ5mDfeKN
vcixi+nkLTCyV1jsHEzteSmGgmAE6SrSMXV+oPz2xLGKEGJJQWS+Ll1l5BD1MmZE
6DqLoe8FHew54M7zniCxkhDIHcpVY3IYcv2gohhaxm9MHkSHaj6bwAGQcORwgGho
ETVr7RXyvCD5Vsr6VqDqknjleP1tLi/gnlzP099SLmGiB6y/v1mW1s3tDpI/F7b7
WWDyHRqW9YfGEPYOmNdELcizW9UxY2MFvK4LlacRaXzzDEXmiP/FK84Qse14Nmyi
6tfqIYe+PRWbA7ztOaBlmDnkhxHcLufB48t4dleUWmj+6VOXQGXef10p4rQNeOo5
N5dJoYqveUJ6Lfln3C25NJcCAwEAAQ==
-----END PUBLIC KEY-----">>}
         }
      }]
    }
  ]}
].

rabbitmq.conf

loopback_users.guest = false
total_memory_available_override_value = 2684354560
listeners.tcp.default = 5672
management.tcp.port = 15672
web_stomp.ws_frame = binary

Current Stomp client setup

      var client = new StompJs.Client({
        brokerURL: 'ws://localhost:5900/ws',
        connectHeaders: {
          login: 'admin',
          passcode: 'guest'
        },
        debug: log => (
          console.log(
            log
          )
        ),
        reconnectDelay: 5 * 1000,
        heartbeatIncoming: 4 * 1000,
        heartbeatOutgoing: 4 * 1000,
      });

Ideal JWT setup

      var client = new StompJs.Client({
        brokerURL: 'ws://localhost:5900/ws',
        connectHeaders: {
          login: 'rabbit',
          passcode: 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FjdGl2ZSI6dHJ1ZSwiX2lkIjoiNWZkNzc0MDY4NzE3NTU2OWFlMTIxNmRmIiwiY29kZSI6IjIwMDAwMDEwNiIsInVzZXJuYW1lIjoiYW50b25pc2NvZGV1cCIsImVtYWlsIjoiYW50b25pc0Bjb2RldXAuc29mdHdhcmUiLCJmaXJzdE5hbWUiOiJBbnRvbmlzIiwibGFzdE5hbWUiOiJQaXNoaWFzIiwib3JnYW5pc2F0aW9uIjoiQ29kZVVwIFNvZnR3YXJlIEx0ZCIsInJvbGUiOnsiX2lkIjoiNWZkMmEyM2VjOTJmOTFjNTFkOTIzMTZiIiwibmFtZSI6ImN1c3RvbWVyIiwicmVhZCI6W3siX2lkIjoiNWZkMmEyM2VjOTJmOTFjNTFkOTIzMTViIiwibmFtZSI6ImFjY291bnRzIn0seyJfaWQiOiI1ZmQyYTIzZWM5MmY5MWM1MWQ5MjMxNWMiLCJuYW1lIjoiY3JtIn0seyJfaWQiOiI1ZmQyYTIzZWM5MmY5MWM1MWQ5MjMxNWQiLCJuYW1lIjoid2FyZWhvdXNlIn1dLCJjcmVhdGUiOltdLCJ1cGRhdGUiOltdLCJtb3ZlIjpbXSwiX192IjowfSwiX192Ijo3LCJzY29wZXMiOlsicmFiYml0bXEuY29uZmlndXJlOiovKiIsInJhYmJpdG1xLndyaXRlOiovKiIsInJhYmJpdG1xLnJlYWQ6Ki8qIl0sImlhdCI6MTYwNzk1NjkzNCwiZXhwIjoxNjA4NTYxNzM0LCJhdWQiOlsiaHR0cHM6Ly9iaXpjb3VyaWVyLmV1IiwicmFiYml0bXEiXSwiaXNzIjoiaHR0cHM6Ly9yZXN0LmJpemNvdXJpZXIuZXUifQ.Ypqa16YuqH3rfwxAQZ_RdJRF21h6jYX07r-zaB3AP_qshU_xBiP9RpFvFkws13i0_X3Ou-qKxSdAF51T1t-Ob5V4LiXLJKsesmZIeIGXs-Dhc79u5UqhOdGIzPgRTlieOIUmrFKsPBWf7FnoR-lgd9gH8ge3Wp2f2vOqU24JsEjkvtlTGLS1aId27UVz0d2qxMLWf-9kLxW4mmuM2UCeRsnznpPaZbAfhq2tHHIy3EtGeIIiOsAE0lM9BfJRF36kjZcpcMZSnhTrkZjiDsrUuiVd-W27MVJRYFVpULkGrpa5RkkDG5ZbwNNSn0VUMZB2PiQTchtNyoffutPzhktxieDO5T0OzrSXl5VAtgZFHi5oPLWtPGVejNiWMFsY9u1ale6NRDSReeQjPPEqzpH-tfnugkwyv_jhL6WnfmoeEBgcuyK7eBvrg7uJbQFdwMrRQXkGn_ATn0XhJWI-Hia3muNbNbvdL0jgkZBv0HFPsx84n3-IEx672_6Wy2qtLtFcnUgGr4ThRVp8PE0ro21JdvjFbwgq9k5Qhv5MA6wgB6nt7vtuP1SZ17ekIPE6izwHUPZsWsqJg6v108H1B13J2yxK5LcdsCb8Z8uRhiRSKt4Cs6MHsZg0GCOjym2YHXyN21Wpw3behq0GxUiSrU4qkADujDb6nNzaLq2_ecn5bOI'
        },
        debug: log => (
          console.log(
            log
          )
        ),
        reconnectDelay: 5 * 1000,
        heartbeatIncoming: 4 * 1000,
        heartbeatOutgoing: 4 * 1000,
      });

You can decode the JWT here

Upvotes: 1

Views: 1697

Answers (1)

Mekroebo
Mekroebo

Reputation: 461

I think that you are missing a scope in your JWT

See the documentation here: https://github.com/rabbitmq/rabbitmq-server/tree/master/deps/rabbitmq_auth_backend_oauth2

It says:

Token scope returned by OAuth 2.0 provider must include RabbitMQ resource scopes that follow a convention used by this plugin: configure:%2F/foo means "configure permissions for 'foo' in vhost '/'") (scope field can be changed using extra_scopes_source in advanced.config file.

(BTW: I coudn't find the "extra_scopes_source" in your advanced.config as well)

Although I didn't test it, failing to provide the scope would logically result in an access denied error.

Upvotes: 1

Related Questions