Skip to content

Commit a74b948

Browse files
authored
Merge pull request #109 from rabbitmq/oauth2
Start support for OAuth 2 token retrieval and refresh
2 parents 7595674 + 380f2f5 commit a74b948

35 files changed

+2440
-144
lines changed

ci/start-broker.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ wait_for_message() {
1212

1313
make -C "${PWD}"/tls-gen/basic
1414

15+
rm -rf rabbitmq-configuration
1516
mkdir -p rabbitmq-configuration/tls
1617
cp -R "${PWD}"/tls-gen/basic/result/* rabbitmq-configuration/tls
1718
chmod o+r rabbitmq-configuration/tls/*

pom.xml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,18 @@
4444
<slf4j.version>1.7.36</slf4j.version>
4545
<netty4.version>4.1.116.Final</netty4.version>
4646
<netty4.iouring.version>0.0.25.Final</netty4.iouring.version>
47-
<netty5.version>5.0.0.Alpha5</netty5.version>
4847
<micrometer.version>1.14.2</micrometer.version>
48+
<gson.version>2.11.0</gson.version>
4949
<logback.version>1.2.13</logback.version>
5050
<junit.jupiter.version>5.11.4</junit.jupiter.version>
5151
<assertj.version>3.27.0</assertj.version>
5252
<mockito.version>5.14.2</mockito.version>
5353
<jqwik.version>1.9.2</jqwik.version>
54-
<amqp-client.version>5.22.0</amqp-client.version>
5554
<micrometer-tracing-test.version>1.4.1</micrometer-tracing-test.version>
5655
<micrometer-docs-generator.version>1.0.4</micrometer-docs-generator.version>
5756
<jose4j.version>0.9.6</jose4j.version>
57+
<commons-lang3.version>3.17.0</commons-lang3.version>
58+
<bouncycastle.version>1.79</bouncycastle.version>
5859
<maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
5960
<maven.dependency.plugin.version>3.8.1</maven.dependency.plugin.version>
6061
<maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
@@ -140,6 +141,13 @@
140141
</dependency>
141142
<!-- End of QPid dependencies -->
142143

144+
<dependency>
145+
<groupId>com.google.code.gson</groupId>
146+
<artifactId>gson</artifactId>
147+
<version>${gson.version}</version>
148+
<optional>true</optional>
149+
</dependency>
150+
143151
<dependency>
144152
<groupId>org.junit.jupiter</groupId>
145153
<artifactId>junit-jupiter-engine</artifactId>
@@ -244,6 +252,19 @@
244252
<scope>test</scope>
245253
</dependency>
246254

255+
<dependency>
256+
<groupId>org.apache.commons</groupId>
257+
<artifactId>commons-lang3</artifactId>
258+
<version>${commons-lang3.version}</version>
259+
<scope>test</scope>
260+
</dependency>
261+
262+
<dependency>
263+
<groupId>org.bouncycastle</groupId>
264+
<artifactId>bcpkix-jdk18on</artifactId>
265+
<version>${bouncycastle.version}</version>
266+
<scope>test</scope>
267+
</dependency>
247268

248269
</dependencies>
249270

src/docs/asciidoc/usage.adoc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,35 @@ include::{test-examples}/Api.java[tag=subscription-listener]
4646
<4> Get the message offset
4747
<5> Store the offset in the external store after processing
4848

49+
=== OAuth 2 Support
50+
51+
The client can authenticate against an OAuth 2 server like https://github.com/cloudfoundry/uaa[UAA].
52+
It uses the https://tools.ietf.org/html/rfc6749#section-4.4[OAuth 2 Client Credentials flow].
53+
The https://www.rabbitmq.com/docs/oauth2[OAuth 2 plugin] must be enabled on the server side and configured to use the same OAuth 2 server as the client.
54+
55+
How to retrieve the OAuth 2 token can be globally configured at the environment level:
56+
57+
.Configuring OAuth 2 token retrieval
58+
[source,java,indent=0]
59+
--------
60+
include::{test-examples}/Api.java[tag=oauth2]
61+
--------
62+
<1> Access the OAuth 2 configuration
63+
<2> Set the token endpoint URI
64+
<3> Authenticate the client application
65+
<4> Set the grant type
66+
<5> Set optional parameters (depends on the OAuth 2 server)
67+
<6> Set the SSL context (e.g. to verify and trust the identity of the OAuth 2 server)
68+
<7> The token can be shared across the environment connections
69+
70+
The environment retrieves tokens and uses them to create AMQP connections.
71+
It also takes care of refreshing the tokens before they expire and of re-authenticating existing connections so the broker does not close them when their token expires.
72+
73+
The environment uses the same token for all the connections it maintains by default, but this can be changed by setting the `shared` flag to `false`.
74+
With `shared = false`, each connection will have its own OAuth 2 token.
75+
76+
The OAuth 2 configuration can be set at the environment level but also at the connection level.
77+
4978
=== Metrics Collection
5079

5180
The library provides the {javadoc-url}/com/rabbitmq/client/amqp/metrics/MetricsCollector.html[`MetricsCollector`] abstraction to collect metrics.

src/main/java/com/rabbitmq/client/amqp/ConnectionSettings.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,17 @@ public interface ConnectionSettings<T> {
154154
*/
155155
Affinity<? extends T> affinity();
156156

157+
/**
158+
* OAuth 2 settings.
159+
*
160+
* <p>OAuth 2 requires RabbitMQ 4.1 or more.
161+
*
162+
* @return OAuth 2 settings
163+
* @see OAuth2Settings
164+
* @since 0.4.0
165+
*/
166+
OAuth2Settings<? extends T> oauth2();
167+
157168
/**
158169
* TLS settings.
159170
*
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// Copyright (c) 2024 Broadcom. All Rights Reserved.
2+
// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
// If you have any questions regarding licensing, please contact us at
17+
18+
package com.rabbitmq.client.amqp;
19+
20+
import javax.net.ssl.SSLContext;
21+
22+
/**
23+
* Configuration to retrieve a token using the <a
24+
* href="https://tools.ietf.org/html/rfc6749#section-4.4">OAuth 2 Client Credentials flow</a>.
25+
*
26+
* <p>OAuth 2 requires RabbitMQ 4.1 or more.
27+
*
28+
* @param <T> the type of object returned by methods, usually the object itself
29+
* @since 0.4.0
30+
*/
31+
public interface OAuth2Settings<T> {
32+
33+
/**
34+
* Set the URI to access to get the token.
35+
*
36+
* <p>TLS is supported by providing a <code>HTTPS</code> URI and setting a {@link SSLContext}. See
37+
* {@link #tls()} for more information. <em>Applications in production should always use HTTPS to
38+
* retrieve tokens.</em>
39+
*
40+
* @param uri access URI
41+
* @return OAuth 2 settings
42+
* @see #tls()
43+
* @see TlsSettings#sslContext(SSLContext)
44+
*/
45+
OAuth2Settings<T> tokenEndpointUri(String uri);
46+
47+
/**
48+
* Set the OAuth 2 client ID
49+
*
50+
* <p>The client ID usually identifies the application that requests a token.
51+
*
52+
* @param clientId client ID
53+
* @return OAuth 2 settings
54+
*/
55+
OAuth2Settings<T> clientId(String clientId);
56+
57+
/**
58+
* Set the secret (password) to use to get a token.
59+
*
60+
* @param clientSecret client secret
61+
* @return OAuth 2 settings
62+
*/
63+
OAuth2Settings<T> clientSecret(String clientSecret);
64+
65+
/**
66+
* Set the grant type to use when requesting the token.
67+
*
68+
* <p>The default is <code>client_credentials</code>, but some OAuth 2 servers can use
69+
* non-standard grant types to request tokens with extra-information.
70+
*
71+
* @param grantType grant type
72+
* @return OAuth 2 settings
73+
*/
74+
OAuth2Settings<T> grantType(String grantType);
75+
76+
/**
77+
* Set a parameter to pass in the request.
78+
*
79+
* <p>The OAuth 2 server may require extra parameters to narrow down the identity of the user.
80+
*
81+
* @param name name of the parameter
82+
* @param value value of the parameter
83+
* @return OAuth 2 settings
84+
*/
85+
OAuth2Settings<T> parameter(String name, String value);
86+
87+
/**
88+
* Whether to share the same token between connections.
89+
*
90+
* <p>Default is <true>true</true> (the token is shared between connections).
91+
*
92+
* @param shared flag to share the token between connections
93+
* @return OAuth 2 settings
94+
*/
95+
OAuth2Settings<T> shared(boolean shared);
96+
97+
/**
98+
* TLS configuration for requesting the token.
99+
*
100+
* @return TLS configuration
101+
*/
102+
TlsSettings<? extends T> tls();
103+
104+
/**
105+
* Connection settings.
106+
*
107+
* @return connections settings
108+
*/
109+
T connection();
110+
111+
/**
112+
* TLS settings to request the OAuth 2 token.
113+
*
114+
* @param <T> the type of object returned by methods, usually the object itself
115+
*/
116+
interface TlsSettings<T> {
117+
118+
/**
119+
* {@link SSLContext} for HTTPS requests.
120+
*
121+
* @param sslContext the SSL context
122+
* @return TLS settings
123+
*/
124+
TlsSettings<T> sslContext(SSLContext sslContext);
125+
126+
/**
127+
* Go back to the general OAuth 2 settings.
128+
*
129+
* @return OAuth 2 settings
130+
*/
131+
OAuth2Settings<T> oauth2();
132+
}
133+
}

0 commit comments

Comments
 (0)