Skip to content

Commit dc7b212

Browse files
Explain additional_scopes_key configuration
1 parent f2b522c commit dc7b212

File tree

2 files changed

+108
-13
lines changed

2 files changed

+108
-13
lines changed

docs/oauth2-examples-keycloak.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ make start-rabbitmq
6969
RabbitMQ is deployed with TLS enabled and Keycloak is configured with the corresponding `redirect_url` which uses https.
7070
:::
7171

72+
:::important
73+
RabbitMQ is configured to read the scopes from the custom claim [extra_scope](https://github.com/rabbitmq/rabbitmq-oauth2-tutorial/blob/next/conf/keycloak/rabbitmq.conf#L11) and
74+
by default from the standard claim `scope`.
75+
However, if your scopes are deep in a map/list structure like `authorization.permissions.scopes`
76+
or under `realm_access.roles` or `resource_access.account.roles`, you can configure
77+
RabbitMQ to use those locations instead. See the section [Use a different token field for the scope](./oauth2#use-different-token-field) for more information.
78+
:::
79+
7280
## Access Management api
7381

7482
To access the management api run the following command. It uses the client [mgt_api_client](https://keycloak:8443/admin/master/console/#/test/clients/c5be3c24-0c88-4672-a77a-79002fcc9a9d/settings) which has the scope [rabbitmq.tag:administrator](https://keycloak:8443/admin/master/console/#/test/client-scopes/f6e6dd62-22bf-4421-910e-e6070908764c/settings).

docs/oauth2.md

Lines changed: 100 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ In chronological order, here is the sequence of events that occur when a client
144144
|--------------------------------------------|-----------
145145
| `auth_oauth2.resource_server_id` | The [Resource Server ID](#resource-server-id)
146146
| `auth_oauth2.resource_server_type` | The Resource Server Type required when using [Rich Authorization Request](#rich-authorization-request) token format
147-
| `auth_oauth2.additional_scopes_key` | Configure the plugin to look for scopes in other fields (maps to `additional_rabbitmq_scopes` in the old format). |
147+
| `auth_oauth2.additional_scopes_key` | [Configure](#use-different-token-field) the plugin to look for scopes in other fields. |
148148
| `auth_oauth2.scope_prefix` | [Configure the prefix for all scopes](#scope-prefix). The default value is `auth_oauth2.resource_server_id` followed by the dot `.` character. |
149149
| `auth_oauth2.preferred_username_claims` | [List of the JWT claims](#preferred-username-claims) to look for the username associated with the token.
150150
| `auth_oauth2.default_key` | ID of the default signing key.
@@ -252,9 +252,6 @@ The following configuration declares two signing keys and configures the kid of
252252

253253
```ini
254254
auth_oauth2.resource_server_id = new_resource_server_id
255-
auth_oauth2.additional_scopes_key = my_custom_scope_key
256-
auth_oauth2.preferred_username_claims.1 = username
257-
auth_oauth2.preferred_username_claims.2 = user_name
258255
auth_oauth2.default_key = id1
259256
auth_oauth2.signing_keys.id1 = test/config_schema_SUITE_data/certs/key.pem
260257
auth_oauth2.signing_keys.id2 = test/config_schema_SUITE_data/certs/cert.pem
@@ -571,26 +568,116 @@ If a symmetric key is used, the configuration looks like this:
571568
572569
### Use a different token field for the scope {#use-different-token-field}
573570
574-
By default the plugin looks for the `scope` key in the token, you can configure the plugin to also look in other fields using the `extra_scopes_source` variable. Values format accepted are scope as **string** or **list**
571+
The plugin always extracts the scopes from the `scope` claim. However,
572+
you can also configure the plugin to look in other claims using the `auth_oauth2.additional_scopes_key` variable.
575573
576-
```ini
577-
auth_oauth2.resource_server_id = my_rabbit_server
578-
auth_oauth2.additional_scopes_key = my_custom_scope_key
579-
```
574+
The scopes found in the `scope` claim must be of these two value types:
575+
- **string separated by spaces** like `my_id.configure:*/* my_id.read:*/* my_id.write:*/*`
576+
- **list** like `["my_id.configure:*/*", "my_id.read:*/*", "my_id.write:*/*"]`
577+
578+
The scopes found in any claim listed in the `auth_oauth2.additional_scopes_key` variable can be
579+
of several types in addition to the two value types supported by the `scope` claim mentioned earlier.
580+
581+
#### Map of scopes indexed by resource_server_id {#map-of-scopes-indexed-by-resource-id}
582+
583+
This is an example of a token where scopes are not yet prefixed with the `resource_server_id`
584+
but are indexed by the `resource_server_id`:
580585
581-
Token sample:
582586
```ini
583587
{
584588
"exp": 1618592626,
585589
"iat": 1618578226,
586590
"aud" : ["my_id"],
587591
...
588-
"scope_as_string": "my_id.configure:*/* my_id.read:*/* my_id.write:*/*",
589-
"scope_as_list": ["my_id.configure:*/*", "my_id.read:*/*", "my_id.write:*/*"],
590-
...
592+
"complex_claim_as_string": {
593+
"rabbitmq": ["configure:*/* read:*/* write:*/*"]
594+
},
595+
"complex_claim_as_list": {
596+
"rabbitmq": ["configure:vhost1/*", "read:vhost1/*", "write:vhost1/*"]
591597
}
598+
...
599+
}
600+
```
601+
602+
With the following plugin configuration, the plugin reads the scopes from two
603+
additional claims: `complex_claim_as_string` and `complex_claim_as_list`.
604+
The plugin reads the scopes and adds the key value as prefix, for instance,
605+
given the scope `configure:*/*` it produces `rabbitmq.configure:*/*`.
606+
607+
```ini
608+
auth_oauth2.resource_server_id = my_rabbit_server
609+
auth_oauth2.additional_scopes_key = complex_claim_as_string complex_claim_as_list
610+
```
611+
612+
#### Scopes nested deep in Maps and Lists
613+
614+
This is the case for tokens issued by **Keycloak** Identity Provider but can be
615+
applied to any token from any provider.
616+
617+
This first token format stores scopes deep in maps and lists.
618+
```json
619+
{
620+
"authorization": {
621+
"permissions": [
622+
{
623+
"scopes": [
624+
"rabbitmq-resource.read:*/*"
625+
],
626+
"rsid": "2c390fe4-02ad-41c7-98a2-cebb8c60ccf1",
627+
"rsname": "allvhost"
628+
},
629+
{
630+
"scopes": [
631+
"rabbitmq-resource.write:vhost1/*"
632+
],
633+
"rsid": "e7f12e94-4c34-43d8-b2b1-c516af644cee",
634+
"rsname": "vhost1"
635+
},
636+
{
637+
"scopes": [
638+
"rabbitmq-resource.tag:administrator"
639+
],
640+
"rsid": "12ac3d1c-28c2-4521-8e33-0952eff10bd9"
641+
}
642+
]
643+
},
644+
"scope": "email profile rabbitmq-resource.tag:monitoring",
645+
}
592646
```
593647
648+
Given the following configuration:
649+
```ini
650+
auth_oauth2.resource_server_id = my_rabbit_server
651+
auth_oauth2.additional_scopes_key = authorization.permissions.scopes
652+
```
653+
654+
The plugin navigates the token structure following this logic:
655+
1. It looks up the claim `authorization`.
656+
2. It finds a map, it then looks for the next claim `permissions`.
657+
3. This time, it finds a list of maps. It goes over all the items in the list.
658+
4. For each map in the list, it looks up the next claim `scopes`.
659+
5. The value can be a list of scopes or a comma-separated string of scopes or
660+
a [map of scopes indexed by resource_server_id](#map-of-scopes-indexed-by-resource-id).
661+
662+
Additionally, the plugin always reads the scopes from the official `scope` claim.
663+
664+
With the above token and plugin's configuration, the list of scopes are following:
665+
- `rabbitmq-resource.tag:monitoring`
666+
- `rabbitmq-resource.read:*/*`
667+
- `rabbitmq-resource.write:vhost1/*`
668+
- `rabbitmq-resource.tag:administrator`
669+
670+
In summary, the plugin is able to navigate the token to find the scopes
671+
using the appropriate path. Each intermediary stage, for instance, after
672+
finding `authorization` and/or `permissions` keys, the value can be another Map or
673+
a List of Maps. The last stage, after finding the last `scopes` key, the value
674+
can be any of any of the value types explained in the previous section.
675+
676+
These are:
677+
- **string separated by spaces** like `my_id.configure:*/* my_id.read:*/* my_id.write:*/*`
678+
- **list** like `["my_id.configure:*/*", "my_id.read:*/*", "my_id.write:*/*"]`
679+
- [Map of scopes indexed by resource server id](#map-of-scopes-indexed-by-resource-id)
680+
594681
### Preferred username claims {#preferred-username-claims}
595682
596683
The username associated with the token must be available to RabbitMQ so that this username is displayed in the RabbitMQ Management UI.

0 commit comments

Comments
 (0)