Skip to content

Commit e063a8f

Browse files
Merge pull request #1504 from rabbitmq/oidc_idp_initiated_login
OAuth2 doc changes
2 parents d372f16 + 18c82d2 commit e063a8f

6 files changed

+137
-47
lines changed

site/management.md

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,25 +288,32 @@ rabbitmqctl set_user_tags full_access administrator
288288
RabbitMQ can be configured to use [JWT-encoded OAuth 2.0 access tokens](https://github.com/rabbitmq/rabbitmq-auth-backend-oauth2) to authenticate client applications and management UI users. When doing so, the management UI does
289289
not automatically redirect users to authenticate
290290
against the OAuth 2 server, this must be configured separately. Currently,
291-
RabbitMQ has been tested against the following Authorization servers:
291+
**Authorization code flow with PKCE** is tested with the following Authorization servers:
292292

293293
* [UAA](https://github.com/cloudfoundry/uaa)
294294
* [Keycloak](https://www.keycloak.org/)
295295
* [Auth0](https://auth0.com/)
296296
* [Azure](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/auth-oauth2)
297297

298+
**Important**: from the OAuth 2.0 point of view, the RabbitMQ Management UI is a **public app** which
299+
means it cannot securely store credentials such as the *client_secret*. This means that RabbitMQ does not need to present a client_secret when authenticating users.
300+
301+
It is usually possible to configure the OAuth client as a **public app** with the authorization server that you are using.
302+
If target authorization server only supports a **confidential app** or it requires a *client_secret*,
303+
then a *client_secret* **must** be configured using the `oauth_client_secret` setting.
304+
298305
To redirect users to the UAA server to authenticate, use the following configuration:
299306

300307
<pre class="lang-ini">
301308
management.enable_uaa = true
302309
management.oauth_enabled = true
303310
management.oauth_client_id = rabbit_user_client
304-
management.oauth_client_secret = rabbit_user_client_secret
305311
management.oauth_provider_url = https://my-uaa-server-host:8443/uaa
306312
</pre>
307313

308-
> IMPORTANT: Since RabbitMQ 3.10, RabbitMQ uses `authorization_code` grant type. `implicit` flow has been
309-
deprecated.
314+
> **Important**: Since RabbitMQ 3.10, RabbitMQ uses `authorization_code` grant type. `implicit` flow is deprecated.
315+
316+
> **Important**: `management.oauth_client_secret` is an optional setting. It is only required when the authorization server used requires it
310317
311318
### Allow Basic and OAuth 2 authentication
312319

@@ -333,7 +340,6 @@ management.disable_basic_auth = true
333340
management.enable_uaa = true
334341
management.oauth_enabled = true
335342
management.oauth_client_id = rabbit_user_client
336-
management.oauth_client_secret = rabbit_user_client_secret
337343
management.oauth_provider_url = https://my-uaa-server-host:8443/uaa
338344
</pre>
339345

@@ -348,12 +354,6 @@ curl -i --header "authorization: Bearer &lt;token&gt;" http://localhost:15672/ap
348354
This is true for all endpoints except `GET /definitions` and `POST /definitions`. Those
349355
endpoints require the token to be passed in the `token` query string parameter.
350356

351-
### Minimum scope required and how the UI determines the username from the token
352-
353-
At a minimum, RabbitMQ requires the the `openid` scope because it uses some claims in the *id token* to determine the username and to display this username on the top right corner of the management UI. The *id token* is returned by the Authorization server if the `openid` scope is included in the authorization request.
354-
355-
RabbitMQ reads the `user_name` claim from the *id_token*. If the token does not contain the `user_name`, RabbitMQ uses the `sub` claim.
356-
357357
### Configure which scopes RabbitMQ requests to the authorization server
358358

359359
It is possible to configure which OAuth 2.0 scopes RabbitMQ should claim when redirecting the user to the authorization server.
@@ -373,6 +373,8 @@ such as:
373373
* <*resource_server_id*>`.tag:administrator`
374374
* <*resource_server_id*>`.read:*/*/*`
375375

376+
The scopes are configured using the `management.oauth_scopes` setting. The value must be a space-separated list of scopes.
377+
376378
### Configure OpenID Connect Discovery endpoint
377379

378380
By default, RabbitMQ assumes the OpenID Connect Discovery endpoint is at `<management.oauth_provider_url>/.well-known/openid-configuration`. If your endpoint differs, you can set yours via the `management.oauth_metadata_url` setting.
@@ -395,6 +397,28 @@ For instance, if you configured the CSP header with the value `default-src 'self
395397

396398
In addition to the `connect-src` CSP header, RabbitMQ also needs the CSP directives `unsafe-eval` `unsafe-inline`, otherwise the OAuth 2.0 functionality may not work.
397399

400+
### Identity-Provider initiated logon
401+
402+
By default, the RabbitMQ Management UI uses the OAuth 2.0 **authorization code flow** to authenticate and authorize users.
403+
However, there are scenarios where users preferred to be automatically redirected to RabbitMQ without getting
404+
involved in additional logon flows. This is common in Web Portals where with a single click, users navigate
405+
straight to a RabbitMQ cluster's management UI with a token obtained under the covers. This is known as
406+
**Identity-Provider initiated logon**.
407+
408+
RabbitMQ exposes a new setting called `management.oauth_initiated_logon_type` whose default value `sp_initiated`.
409+
To enable an **Identity-Provider initiated logon** you set it to `idp_initiated`.
410+
411+
After you set `management.oauth_initiated_logon_type` to `idp_initiated` and
412+
`oauth_enabled: true` and `oauth_provider_url` are configured, the management UI exposes the HTTP endpoint `/login` which accepts `content-type: application/x-www-form-urlencoded` and it expects the JWT token in the `access_token` form field. This is the endpoint where the web portal would redirect users to access the RabbitMQ Management ui.
413+
414+
This is the minimum required configuration for a RabbitMQ cluster configured with `idp_initiated` logon type:
415+
416+
<pre class="lang-ini">
417+
management.oauth_enabled = true
418+
management.oauth_initiated_logon_type = idp_initiated
419+
management.oauth_provider_url = https://my-web-portal
420+
</pre>
421+
398422

399423
## <a id="http-api" class="anchor" href="#http-api">HTTP API</a>
400424

site/oauth2-examples-azure.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,6 @@ When using **Azure AD as OAuth 2.0 server**, your client app (in our case Rabbit
4949

5050
![Azure AD JWKS URI](./img/oauth2/azure-ad-jwks-uri.png)
5151

52-
## Create a secret for your app
53-
54-
Your application needs a **client secret** to prove its identity when requesting a token.
55-
56-
1. Still on the **App registrations** page, in the left-hand menu, click on **Certificates & Secrets**, then select the **Client secrets** tab.
57-
58-
2. In the **Certificates & Secrets** pane, click on **New Client Secret** and, on the right pane that has just opened, enter a description for the secret and choose an expiration time.
59-
60-
3. Click on **Add**.
61-
62-
<g-emoji class="g-emoji" alias="warning" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/26a0.png">⚠️</g-emoji> **IMPORTANT**: Immediately note the value of the secret (as you won't be able to get it later and you will need it to configure the `rabbitmq_auth_backend_oauth2` on RabbitMQ side).
6352

6453
## Create OAuth 2.0 roles for your app
6554

@@ -138,7 +127,6 @@ The configuration on Azure side is done. You now have to configure RabbitMQ to u
138127
Update it with the following values (you should have noted these in the previous steps):
139128
* **Tenant ID** associated to the app that you registered in Azure AD
140129
* **Application ID** associated to the app that you registered in Azure AD
141-
* Value of the **secret** you created for your app in Azure AD
142130
* Value of the **jwks_uri** key from `https://login.microsoftonline.com/{TENANT_ID}/v2.0/.well-known/openid-configuration`
143131

144132
<pre class="lang-bash">
@@ -150,7 +138,6 @@ $ vi rabbitmq.config
150138
{rabbitmq_management, [
151139
{oauth_enabled, true},
152140
{oauth_client_id, "PUT YOUR AZURE AD APPLICATION ID"},
153-
{oauth_client_secret, "PUT YOUR AZURE AD APPLICATION SECRET"},
154141
{oauth_provider_url, "https://login.microsoftonline.com/AZURE_AD_TENANT_ID"}
155142
]},
156143
{rabbitmq_auth_backend_oauth2, [

site/oauth2-examples-keycloak.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@ rather than `legacy-token-key`.
107107

108108
### Configure Client
109109

110-
For backend applications which uses **Client Credentials flow** you create a **Client** with:
110+
For backend applications which uses **Client Credentials flow**, you can create a **Client** with:
111111

112-
* **Access Type** : `confidential`
113-
* With all the other flows disabled: Standard Flow, Implicit Flow, Direct Access Grants
112+
* **Access Type** : `public`
113+
* Turn off `Standard Flow`, `Implicit Flow`, and `Direct Access Grants`
114114
* With **Service Accounts Enabled** on. If it is not enabled you do not have the tab `Credentials`
115-
* In tab `Credentials` you have the client id secret
115+
* In the `Credentials` tab, you have the `client id`
116116

117117

118118
### Configure Client scopes

site/oauth2-examples-oauth0.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ list of users which have this role.
7474

7575
1. From Auth0 dashboard, go to **Settings > List of Valid Keys**, and **Copy Signing Certificate** from the **CURRENTLY USED** signing key.
7676

77-
2. Create `/tmp/certiicate.pem` and paste the certificate.
77+
2. Create `/tmp/certificate.pem` and paste the certificate.
7878

7979
3. Run `openssl x509 -in /tmp/certificate.pem -pubkey -noout > /tmp/public.pem` to extract the public key from the certificate and paste the public key into `rabbitmq.config`.
8080

site/oauth2-examples.md

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ To understand the details of how to configure RabbitMQ with Oauth2, go to the [U
2222

2323
* [Prerequisites to follow this guide](#prerequisites)
2424
* [Getting started with UAA and RabbitMQ](#getting-started-with-uaa-and-rabbitmq)
25-
* [Use Access tokens](#use-access-tokens)
26-
- [Management user accessing the Management UI](#management-user-accessing-the-management-ui)
27-
- [Monitoring agent accessing management REST api](#monitoring-agent-accessing-management-rest-api)
25+
* [Access Management UI using OAuth 2.0 tokens](#access-management-ui)
26+
- [Service-Provider initiated logon](#service-provider-initiated-logon)
27+
- [Identity-Provider initiated logon](#identity-provider-initiated-logon)
28+
* [Access other protocols using OAuth 2.0 tokens](#access-other-protocols)
29+
- [Management REST api](#monitoring-agent-accessing-management-rest-api)
2830
- [AMQP protocol](#amqp-protocol)
2931
- [JMS protocol](#jms-protocol)
3032
- [MQTT protocol](#mqtt-protocol)
@@ -78,20 +80,26 @@ has to be configured to validate any of the two types of digital signatures.
7880
Given that asymmetrical keys is the most widely used option, you are going to focus on how to
7981
configure RabbitMQ with them.
8082

81-
Run the following 3 commands to get the environment ready to see Oauth 2.0 plugin in action:
83+
Run the following 2 commands to get the environment ready to see Oauth 2.0 plugin in action:
8284

8385
1. `make start-uaa` to get UAA server running
84-
2. `make setup-uaa-users-and-clients` to install uaac client; connect to UAA server and set ups users, group, clients and permissions
85-
3. `make start-rabbitmq` to start RabbitMQ server
86+
2. `make start-rabbitmq` to start RabbitMQ server
8687

8788
The last command starts a RabbitMQ server with [this](https://github.com/rabbitmq/rabbitmq-oauth2-tutorial/blob/main/conf/uaa/rabbitmq.config) configuration file.
8889

90+
## <a id="access-management-ui" class="anchor" href="#access-management-ui">Access Management UI using OAuth 2.0 tokens</a>
8991

90-
## <a id="use-access-tokens" class="anchor" href="#use-oauth-tokens">Use access tokens</a>
92+
The RabbitMQ Management UI can be configured with one of these two login modes:
9193

92-
The following subsections demonstrate how to use access tokens with any messaging protocol and also to access the management ui and rest api.
94+
* [Service-Provider initiated logon](#service-provider-initiated-logon): this is the default and traditional OAuth 2.0 logon mode.
95+
When the user visits the RabbitMQ Management UI, it shows a button with the label `Click here to logon`. When the user clicks it,
96+
the logon process starts by redirecting to the configured **Authorization Server**.
97+
* [Identity-Provider initiated logon](#identity-provider-initiated-logon): this mode is opposite to the previous mode.
98+
The user must first access the RabbitMQ Management's `/login` endpoint with a token. If the token is valid, the user is allowed to access the RabbitMQ Management UI.
99+
This mode is very useful for Web sites which allow users to access the RabbitMQ Management UI with a single click.
100+
The original Web site get a token on user's behalf and redirects the user to the RabbitMQ Management's `/login` endpoint.
93101

94-
### <a id="management-user-accessing-the-management-ui" class="anchor" href="#management-user-accessing-the-management-ui">Management user accessing the Management UI</a>
102+
### <a id="service-provider-initiated-logon" class="anchor" href="#service-provider-initiated-logon">Service-Provider initiated logon</a>
95103

96104
The first time an end user arrives to the management UI, they are redirected to the configured OAuth 2.0 provider to authenticate.
97105
Once they successfully authenticate, the user is redirected back to RabbitMQ
@@ -117,23 +125,72 @@ UAA has previously been configured and seeded with two users:
117125

118126
Now navigating to the [local node's management UI](http://localhost:15672) and login using any of those two users.
119127

120-
The user displayed by the management ui is not the user name but `rabbitmq_client` which is the
121-
identity of RabbitMQ to work on half of the user.
122-
123128
This is a token issued by UAA for the `rabbit_admin` user thru the redirect flow you just saw above.
124129
It was signed with the symmetric key.
125130

126131
![JWT token](./img/oauth2/admin-token-signed-sym-key.png)
127132

128-
### <a id="monitoring-agent-accessing-management-rest-api" class="anchor" href="#monitoring-agent-accessing-management-rest-api-2">Monitoring agent accessing management REST api</a>
133+
To configure the RabbitMQ Management UI with OAuth 2.0, the following configuration entries are required
134+
in `advanced.config`:
135+
136+
<pre class="lang-erlang">
137+
...
138+
{rabbitmq_management, [
139+
{oauth_enabled, true},
140+
{oauth_client_id, "rabbit_client_code"},
141+
{oauth_provider_url, "http://localhost:8080"},
142+
...
143+
]},
144+
</pre>
145+
146+
### <a id="identity-provider-initiated-logon" class="anchor" href="#identity-provider-initiated-logon">Identity-Provider initiated logon</a>
147+
148+
When RabbitMQ is provided as a service from a web portal, it is easy to navigate to the RabbitMQ Management UI
149+
with a single click. The web portal retrieves a token before taking the user to the RabbitMQ Management UI web page.
150+
151+
<pre class="lang-plain">
152+
[ Idp | WebPortal ] ----&gt; 2. /login [access_token: TOKEN]---- [ RabbitMQ Cluster ]
153+
/|\ | /|\
154+
| +--------+
155+
1. rabbit_admin from a browser 3. validate token
156+
</pre>
157+
158+
How it works, firstly, the `rabbit_admin` user navigates to the web portal and clicks on the hyperlink associated with a RabbitMQ
159+
cluster. Next, the web portal obtains a token and redirects the user to RabbitMQ `/login` endpoint with the token within the HTTP form field `access_token`. Finally,
160+
RabbitMQ validates the token in the http request and if it is valid, it redirects the user to the overview page.
161+
162+
By default, the RabbitMQ Management UI is configured with **service-provider initiated logon**, to configure **Identity-Provider initiated logon**,
163+
add one entry to `advanced.config`. For example:
164+
165+
<pre class="lang-erlang">
166+
...
167+
{rabbitmq_management, [
168+
{oauth_enabled, true},
169+
{oauth_client_id, "rabbit_client_code"},
170+
{oauth_provider_url, "http://localhost:8080"},
171+
{oauth_initiated_logon_type, idp_initiated},
172+
...
173+
]},
174+
</pre>
175+
176+
**Important**: when the user logs out, or its RabbitMQ session expired, or the token expired, the user is directed to the
177+
RabbitMQ Management landing page which has a **Click here to login** button.
178+
The user is never automatically redirected back to the url configured in the `oauth_provider_url`.
179+
It is only when the user clicks **Click here to login** , the user is redirected to the configured url in `oauth_provider_url`.
180+
181+
## <a id="access-other-protocols" class="anchor" href="#access-other-protocols">Access other protocols using OAuth 2.0 tokens</a>
182+
183+
The following subsections demonstrate how to use access tokens with any messaging protocol and also to access the management rest api.
184+
185+
### <a id="monitoring-agent-accessing-management-rest-api" class="anchor" href="#monitoring-agent-accessing-management-rest-api-2">Management REST api</a>
129186

130187
In this scenario a monitoring agent uses RabbitMQ HTTP API to collect monitoring information.
131188
Because it is not an end user, or human, you refer to it as a *service account*.
132189
This *service account* could be our `mgt_api_client` client you created in UAA with the `monitoring` *user tag*.
133190

134191
This *monitoring agent* would use the *client credentials* or *password* grant flow to authenticate (1) with
135192
UAA and get back a JWT token (2). Once it gets the token, it sends (3) a HTTP request
136-
to the RabbitMQ management endpoint passing the JWT token.
193+
to the RabbitMQ management endpoint passing the JWT token within the `Authorization` header as a *Bearer token*.
137194

138195
<pre class="lang-plain">
139196
[ UAA ] [ RabbitMQ ]
@@ -148,7 +205,7 @@ to the RabbitMQ management endpoint passing the JWT token.
148205
The following command launches the browser with `mgt_api_client` client with a JWT token previously obtained from UAA:
149206

150207
<pre class="lang-bash">
151-
make curl url=http://localhost:15672/api/overview client_id=mgt_api_client secret=mgt_api_client
208+
make curl-uaa url=http://localhost:15672/api/overview client_id=mgt_api_client secret=mgt_api_client
152209
</pre>
153210

154211

@@ -293,7 +350,7 @@ a message to a mqtt topic ([scopes-for-mqtt.json](jwts/scopes-for-mqtt.json))
293350
it is any "routing-key" because that is translated to a topic/queue.
294351

295352
You are going to publish a mqtt message by running the following command. If you have not run any of the
296-
previous use cases, you need to launch rabbitmq first like this `make start-uaa`.
353+
previous use cases, you need to launch rabbitmq first like this `make start-rabbitmq`.
297354

298355
<pre class="lang-bash">
299356
make start-mqtt-publish TOKEN=$(bin/jwt_token scopes-for-mqtt.json legacy-token-key private.pem public.pem)
@@ -688,12 +745,14 @@ The following configuration snippets demonstrate these steps:
688745
<pre class="lang-erlang">
689746
[
690747
{rabbitmq_management, [
748+
%% eanble Oauth
749+
{oauth_enabled, true},
691750
%% use UAA
692751
{enable_uaa, true},
693752
%% OAuth 2 identity server client ID
694-
{uaa_client_id, "rabbit_client"},
753+
{oauth_client_id, "rabbit_client"},
695754
%% UAA endpoint location
696-
{uaa_location, "http://localhost:8080/uaa"}
755+
{oauth_provider_url, "http://localhost:8080"}
697756
]},
698757
].
699758
</pre>

0 commit comments

Comments
 (0)