rabbitmq-server icon indicating copy to clipboard operation
rabbitmq-server copied to clipboard

Drop built-in support for keycloak token format (potential breaking change)

Open MarcialRosales opened this issue 1 year ago • 2 comments

Is your feature request related to a problem? Please describe.

RabbitMQ has been supporting a token format used by Keycloak which carried the tokens in a map whose key is permissions and this map is the value of the token's claim called authorization.

This is an adhoc token layout that it is not necessary to be supported in code but instead via configuration. Should Keycloak ever changed this layout, users can adjust their configuration accordingly without having to make a code change in RabbitMQ.

JWT Keycloak format 1: (not supported in code)

{
  "jti": "865a14bc-d1d7-4b81-8d14-94c4af2bd61f",
  "exp": 1586670977,
  "nbf": 0,
  "iat": 1586670677,
  "iss": "http://localhost:8090/auth/realms/wstutorial",
  "aud": "account",
  "sub": "e4713c5f-d662-4156-93ee-5110ec6007bd",
  "typ": "Bearer",
  "azp": "demo-app",
  "auth_time": 0,
  "session_state": "3aa0f14a-2178-41b1-bff8-fb6364ac1865",
  "acr": "1",
  "realm_access": {
    "roles": [
      "offline_access",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "profile email",
  "email_verified": false,
  "preferred_username": "johndoe"
}

Keycloak JWT format 2: (supported in code)

{
  "authorization": {
    "permissions": [
      {
        "scopes": [
          "rabbitmq-resource.read:*/*"
        ],
        "rsid": "2c390fe4-02ad-41c7-98a2-cebb8c60ccf1",
        "rsname": "allvhost"
      },
      {
        "scopes": [
          "rabbitmq-resource-read"
        ],
        "rsid": "e7f12e94-4c34-43d8-b2b1-c516af644cee",
        "rsname": "vhost1"
      },
      {
        "rsid": "12ac3d1c-28c2-4521-8e33-0952eff10bd9",
        "rsname": "Default Resource"
      }
    ]
  },
  "scope": "email profile",
}

Describe the solution you'd like

Users of keycloak who depend on the token format 2 will have to modify their RabbitMQ configuration to tell RabbitMQ where to get the scope from.

auth_oauth2.additional_scopes_key = authorization.permissions.scope 

With the above configuration, RabbitMQ navigates the map structure. First it looks up the claim authorization from the token. It may return a map or a list of maps. If it is a map, it looks up the next keyword in the map. It finds the keyword permissions. It returns this time a list rather than a map. RabbitMQ iterates over the list and if the list's element is a map and has the next keyword, scope, it extracts them and it continues iterating the list.

Users who depend on the token format 1 will have to modify their RabbitMQ configuration to the following:

auth_oauth2.additional_scopes_key = resource_access.account.roles  real_access.roles

This format is simpler than the previous format as it only combines map objects as opposed to maps and lists.

If the user is already using auth_oauth2.additional_scopes_key, e.g. auth_oauth2.additional_scopes_key = roles the user can use any of these two configuration layouts:

auth_oauth2.additional_scopes_key = authorization.permissions.scope roles

or

auth_oauth2.additional_scopes_key.1 = authorization.permissions.scope 
auth_oauth2.additional_scopes_key.2 = roles

Describe alternatives you've considered

No response

Additional context

No response

MarcialRosales avatar Sep 17 '24 14:09 MarcialRosales