Use multiple OAuth 2.0 servers and/or audiences
Demonstrate how to authenticate using the OAuth 2.0 protocol and several OAuth resources using the following flows:
- Access AMQP protocol
- Access Management UI
Prerequisites
- Docker
Single OAuth 2.0 vs Multiple OAuth 2.0 resources
All the examples demonstrated by this tutorial, except for this use case, configure a single resource_server_id and therefore a single OAuth 2.0 server.
You could encounter scenarios where some management users and/or applications are registered in
different OAuth2 servers or they could be registered on the same OAuth2 server however they could refer to RabbitMQ with different audience values. When this happens, you have to declare as many OAuth2 resources as audiences and/or authorization servers. The following section demonstrates a scenario where users are declared in Keycloak however they refer to RabbitMQ with two distinct audience, one rabbit_prod and the other rabbit_dev.
AMQP clients and management users registered in same OAuth 2.0 server but with different audience
RabbitMQ is configured with two OAuth2 resources one called rabbit_prod and another rabbit_dev. For example purposes, let's say, the production team refer to RabbitMQ with the rabbit_prod audience. And the development team with the rabbit_dev audience.
As both teams are registered in the same OAuth2 server you are going to configure its settings such as jwks_url at the
root level so that both resources share the same configuration.
In the past, RabbitMQ imposed a restriction where the scopes had to be prefixed with the name of the resource/audience. For instance, if resource_server_id was rabbitmq1, all scopes had to be prefixed with the value rabbitmq1, for example rabbitmq1.tag:administrator.
Since RabbitMQ 3.11, you can configure the scope's prefix independent from the resource_id/audience. This is exactly what this scenario uses which configures the scope prefix with the value rabbitmq. so that all scopes, regardless of the resource, have the same prefix.
Test applications accessing AMQP protocol with their own audience
This is a summary of the configuration, found in rabbitmq.conf:
- There are two OAuth2 clients (
prod_produceranddev_producer) declared in keycloak and configured to access their respective audience:rabbit_prodandrabbit_dev - RabbitMQ OAuth2 plugin is configured with two resources:
rabbit_prodandrabbit_devauth_oauth2.resource_servers.1.id = rabbit_prod
auth_oauth2.resource_servers.2.id = rabbit_dev - Also RabbitMQ OAuth2 plugin is configured with common settings for the two resources declared above
auth_oauth2.preferred_username_claims.1 = preferred_username
auth_oauth2.preferred_username_claims.2 = user_name
auth_oauth2.preferred_username_claims.3 = email
auth_oauth2.jwks_url = https://keycloak:8443/realms/test/protocol/openid-connect/certs
auth_oauth2.scope_prefix = rabbitmq.
auth_oauth2.https.peer_verification = verify_peer
auth_oauth2.https.cacertfile = /etc/rabbitmq/keycloak-cacert.pem
Follow these steps to deploy Keycloak and RabbitMQ:
-
Launch Keycloak. Check out Admin page with the credentials
admin:adminmake start-keycloak -
Launch RabbitMQ
export MODE="multi-keycloak"
make start-rabbitmq -
Launch the AMQP producer registered in Keycloak with the client_id
prod_producers and with the permission to access therabbit_prodresource, and with the scopesrabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*make start-perftest-producer-with-token PRODUCER=prod_producer TOKEN=$(bin/keycloak/token prod_producer PdLHb1w8RH1oD5bpppgy8OF9G6QeRpL9)This is an access token generated for
prod_producer.{
"exp": 1690974839,
"iat": 1690974539,
"jti": "c8edec50-5f29-4bd0-b25b-d7a46dc3474e",
"iss": "http://localhost:8081/realms/test",
"aud": "rabbit_prod",
"sub": "826065e7-bb58-4b65-bbf7-8982d6cca6c8",
"typ": "Bearer",
"azp": "prod_producer",
"acr": "1",
"realm_access": {
"roles": [
"default-roles-test",
"offline_access",
"producer",
"uma_authorization"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "profile email rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*",
"clientId": "prod_producer",
"clientHost": "172.18.0.1",
"email_verified": false,
"preferred_username": "service-account-prod_producer",
"clientAddress": "172.18.0.1"
} -
Similarly, launch AMQP producer
dev_producer, registered in Keycloak too but with the permission to accessrabbit_devresource:make start-perftest-producer-with-token PRODUCER=dev_producer TOKEN=$(bin/keycloak/token dev_producer z1PNm47wfWyulTnAaDOf1AggTy3MxX2H)
Test Management UI accessed via two separate resources
This is a summary of the configuration, found in rabbitmq.conf:
- There are two users declared in Keycloak:
prod_useranddev_user - The two resources:
rabbit_prodandrabbit_devare declared in the RabbitMQ Management Plugin with their own OAuth2 client (rabbit_prod_mgt_uiandrabbit_dev_mgt_ui) scopes, and the label associated with each resource.management.oauth_resource_servers.1.id = rabbit_prod
management.oauth_resource_servers.1.client_id = rabbit_prod_mgt_ui
management.oauth_resource_servers.1.label = RabbitMQ Production
management.oauth_resource_servers.1.scopes = openid profile rabbitmq.tag:administrator
management.oauth_resource_servers.2.id = rabbit_dev
management.oauth_resource_servers.2.client_id = rabbit_dev_mgt_ui
management.oauth_resource_servers.2.label = RabbitMQ Development
management.oauth_resource_servers.2.scopes = openid profile rabbitmq.tag:management - As there is only one OAuth2 server, both resources share the same
provider_url:management.oauth_provider_url = http://0.0.0.0:8081/realms/test - Each OAuth2 client,
rabbit_prod_mgt_uiandrabbit_dev_mgt_ui, is declared in Keycloak so that they can only emit tokens for their respective audience, be itrabbit_prodandrabbit_devrespectively.
Follow the steps:
- Go to the RabbitMQ Management UI
- Select
RabbitMQ Productionresource - Login as
prod_user:prod_user - Keycloak prompts you to authorize various scopes for
prod_user - You should now get redirected to the Management UI as
prod_useruser
Now, logout and repeat the same steps for dev_user user. For this user, RabbitMQ is configured to request the rabbitmq.tag:management scope only.
Note: In step 3, if you login as the dev_user, RabbitMQ will not authorize the dev_user because RabbitMQ is configured to request the scope: rabbitmq.tag:administrator for RabbitMQ Production. The dev_user does not have the rabbitmq.tag:administrator scope, it has the rabbitmq.tag:management scope. In this scenario, the dev_user gets a token which has none of the scopes RabbitMQ supports.