Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
MarcialRosales opened this issue Sep 17, 2024 · 2 comments

Comments

@MarcialRosales
Copy link
Contributor

MarcialRosales commented Sep 17, 2024

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

@michaelklishin
Copy link
Member

This sounds really complex for a vendor-specific feature. If Keycloak does change their format, treating "Keycloak v1" and "Keycloak v2" as two different IDPs without this extensive configuration would be much easier.

@MarcialRosales
Copy link
Contributor Author

we already have additional_scopes_key . It is just a matter of separating the key by dots and navigating the maps. I have rejected in the past requests where the scopes were underneath another map ..similar to how Keycloak format works.
I had not invested in this type of flexibility until today when I am refactoring and simplifying the implementation of oauth2 backend. I had forgotten that we had a custom look-up of scopes for keycloak.

With this change we can forget entirely where the scopes are located, pretty much.

It is a much bigger change the feature i am currently working on to support vendors like Azure/Entra and/or OAuth0 and who knows what others in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants