Skip to content

Commit eabdbbe

Browse files
committed
Move OAuth2 token management in dedicated package
1 parent 820921c commit eabdbbe

15 files changed

+147
-74
lines changed

src/main/java/com/rabbitmq/client/amqp/impl/AmqpConnection.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.rabbitmq.client.amqp.impl.Utils.RunnableWithException;
3030
import com.rabbitmq.client.amqp.impl.Utils.StopWatch;
3131
import com.rabbitmq.client.amqp.metrics.MetricsCollector;
32+
import com.rabbitmq.client.amqp.oauth2.CredentialsManager;
3233
import java.time.Duration;
3334
import java.util.*;
3435
import java.util.concurrent.*;
@@ -80,7 +81,7 @@ final class AmqpConnection extends ResourceBase implements Connection {
8081
private final Lock instanceLock = new ReentrantLock();
8182
private final boolean filterExpressionsSupported, setTokenSupported;
8283
private volatile ExecutorService dispatchingExecutorService;
83-
private final Credentials.Registration credentialsRegistration;
84+
private final CredentialsManager.Registration credentialsRegistration;
8485

8586
AmqpConnection(AmqpConnectionBuilder builder) {
8687
super(builder.listeners());
@@ -119,9 +120,9 @@ final class AmqpConnection extends ResourceBase implements Connection {
119120
this.affinityStrategy = null;
120121
}
121122
this.management = createManagement();
122-
Credentials credentials = builder.credentials();
123+
CredentialsManager credentialsManager = builder.credentialsManager();
123124
this.credentialsRegistration =
124-
credentials.register(
125+
credentialsManager.register(
125126
this.name(),
126127
(username, password) -> {
127128
State state = this.state();
@@ -835,7 +836,8 @@ public int hashCode() {
835836
return Objects.hashCode(id);
836837
}
837838

838-
private static class TokenConnectionCallback implements Credentials.AuthenticationCallback {
839+
private static class TokenConnectionCallback
840+
implements CredentialsManager.AuthenticationCallback {
839841

840842
private final ConnectionOptions options;
841843

src/main/java/com/rabbitmq/client/amqp/impl/AmqpConnectionBuilder.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.rabbitmq.client.amqp.impl;
1919

2020
import com.rabbitmq.client.amqp.*;
21+
import com.rabbitmq.client.amqp.oauth2.CredentialsManager;
2122
import java.time.Duration;
2223
import java.util.ArrayList;
2324
import java.util.List;
@@ -162,8 +163,8 @@ AmqpEnvironment environment() {
162163
return environment;
163164
}
164165

165-
Credentials credentials() {
166-
return environment().credentialsFactory().credentials(this.connectionSettings);
166+
CredentialsManager credentialsManager() {
167+
return environment().credentialsManagerFactory().credentials(this.connectionSettings);
167168
}
168169

169170
AmqpRecoveryConfiguration recoveryConfiguration() {

src/main/java/com/rabbitmq/client/amqp/impl/AmqpEnvironment.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class AmqpEnvironment implements Environment {
5454
private final ConnectionUtils.AffinityCache affinityCache = new ConnectionUtils.AffinityCache();
5555
private final EventLoop recoveryEventLoop;
5656
private final ExecutorService recoveryEventLoopExecutorService;
57-
private final CredentialsFactory credentialsFactory = new CredentialsFactory(this);
57+
private final CredentialsManagerFactory credentialsManagerFactory = new CredentialsManagerFactory(this);
5858

5959
AmqpEnvironment(
6060
ExecutorService executorService,
@@ -124,8 +124,8 @@ Clock clock() {
124124
return this.clock;
125125
}
126126

127-
CredentialsFactory credentialsFactory() {
128-
return this.credentialsFactory;
127+
CredentialsManagerFactory credentialsManagerFactory() {
128+
return this.credentialsManagerFactory;
129129
}
130130

131131
@Override

src/main/java/com/rabbitmq/client/amqp/impl/CredentialsFactory.java renamed to src/main/java/com/rabbitmq/client/amqp/impl/CredentialsManagerFactory.java

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,62 +19,66 @@
1919

2020
import com.rabbitmq.client.amqp.CredentialsProvider;
2121
import com.rabbitmq.client.amqp.UsernamePasswordCredentialsProvider;
22+
import com.rabbitmq.client.amqp.oauth2.CredentialsManager;
2223
import com.rabbitmq.client.amqp.oauth2.GsonTokenParser;
2324
import com.rabbitmq.client.amqp.oauth2.HttpTokenRequester;
25+
import com.rabbitmq.client.amqp.oauth2.TokenCredentialsManager;
2426
import java.net.http.HttpClient;
2527
import java.util.concurrent.locks.Lock;
2628
import java.util.concurrent.locks.ReentrantLock;
2729
import java.util.function.Consumer;
2830

29-
final class CredentialsFactory {
31+
final class CredentialsManagerFactory {
3032

31-
private volatile Credentials globalOAuth2Credentials;
33+
private volatile CredentialsManager globalOAuth2CredentialsManager;
3234
private final Lock oauth2CredentialsLock = new ReentrantLock();
3335
private final AmqpEnvironment environment;
3436

35-
CredentialsFactory(AmqpEnvironment environment) {
37+
CredentialsManagerFactory(AmqpEnvironment environment) {
3638
this.environment = environment;
3739
}
3840

39-
Credentials credentials(DefaultConnectionSettings<?> settings) {
41+
CredentialsManager credentials(DefaultConnectionSettings<?> settings) {
4042
CredentialsProvider provider = settings.credentialsProvider();
41-
Credentials credentials;
43+
CredentialsManager credentialsManager;
4244
if (settings.oauth2().enabled()) {
4345
if (settings.oauth2().shared()) {
44-
credentials = globalOAuth2Credentials(settings);
46+
credentialsManager = globalOAuth2Credentials(settings);
4547
} else {
46-
credentials = createOAuth2Credentials(settings);
48+
credentialsManager = createOAuth2Credentials(settings);
4749
}
4850
} else {
4951
if (provider instanceof UsernamePasswordCredentialsProvider) {
5052
UsernamePasswordCredentialsProvider credentialsProvider =
5153
(UsernamePasswordCredentialsProvider) provider;
52-
credentials = new UsernamePasswordCredentials(credentialsProvider);
54+
credentialsManager = new UsernamePasswordCredentialsManager(credentialsProvider);
5355
} else {
54-
credentials = Credentials.NO_OP;
56+
credentialsManager = CredentialsManager.NO_OP;
5557
}
5658
}
57-
return credentials;
59+
return credentialsManager;
5860
}
5961

60-
private Credentials globalOAuth2Credentials(DefaultConnectionSettings<?> connectionSettings) {
61-
Credentials result = this.globalOAuth2Credentials;
62+
private CredentialsManager globalOAuth2Credentials(
63+
DefaultConnectionSettings<?> connectionSettings) {
64+
CredentialsManager result = this.globalOAuth2CredentialsManager;
6265
if (result != null) {
6366
return result;
6467
}
6568

6669
this.oauth2CredentialsLock.lock();
6770
try {
68-
if (this.globalOAuth2Credentials == null) {
69-
this.globalOAuth2Credentials = createOAuth2Credentials(connectionSettings);
71+
if (this.globalOAuth2CredentialsManager == null) {
72+
this.globalOAuth2CredentialsManager = createOAuth2Credentials(connectionSettings);
7073
}
71-
return this.globalOAuth2Credentials;
74+
return this.globalOAuth2CredentialsManager;
7275
} finally {
7376
this.oauth2CredentialsLock.unlock();
7477
}
7578
}
7679

77-
private Credentials createOAuth2Credentials(DefaultConnectionSettings<?> connectionSettings) {
80+
private CredentialsManager createOAuth2Credentials(
81+
DefaultConnectionSettings<?> connectionSettings) {
7882
DefaultConnectionSettings.DefaultOAuth2Settings<?> settings = connectionSettings.oauth2();
7983
Consumer<HttpClient.Builder> clientBuilderConsumer;
8084
if (settings.tlsEnabled()) {
@@ -92,7 +96,7 @@ private Credentials createOAuth2Credentials(DefaultConnectionSettings<?> connect
9296
clientBuilderConsumer,
9397
null,
9498
new GsonTokenParser());
95-
return new TokenCredentials(
99+
return new TokenCredentialsManager(
96100
tokenRequester, environment.scheduledExecutorService(), settings.refreshDelayStrategy());
97101
}
98102
}

src/main/java/com/rabbitmq/client/amqp/impl/DefaultConnectionSettings.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static java.util.stream.Collectors.*;
2222

2323
import com.rabbitmq.client.amqp.*;
24+
import com.rabbitmq.client.amqp.oauth2.TokenCredentialsManager;
2425
import java.io.IOException;
2526
import java.net.URI;
2627
import java.net.URISyntaxException;
@@ -512,7 +513,7 @@ static class DefaultOAuth2Settings<T> implements OAuth2Settings<T> {
512513
private String grantType = "client_credentials";
513514
private boolean shared = true;
514515
private Function<Instant, Duration> refreshDelayStrategy =
515-
TokenCredentials.DEFAULT_REFRESH_DELAY_STRATEGY;
516+
TokenCredentialsManager.DEFAULT_REFRESH_DELAY_STRATEGY;
516517

517518
DefaultOAuth2Settings(DefaultConnectionSettings<T> connectionSettings) {
518519
this.connectionSettings = connectionSettings;

src/main/java/com/rabbitmq/client/amqp/impl/UsernamePasswordCredentials.java renamed to src/main/java/com/rabbitmq/client/amqp/impl/UsernamePasswordCredentialsManager.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@
1818
package com.rabbitmq.client.amqp.impl;
1919

2020
import com.rabbitmq.client.amqp.UsernamePasswordCredentialsProvider;
21+
import com.rabbitmq.client.amqp.oauth2.CredentialsManager;
2122

22-
final class UsernamePasswordCredentials implements Credentials {
23+
final class UsernamePasswordCredentialsManager implements CredentialsManager {
2324

2425
private final UsernamePasswordCredentialsProvider provider;
2526
private final Registration registration;
2627

27-
UsernamePasswordCredentials(UsernamePasswordCredentialsProvider provider) {
28+
UsernamePasswordCredentialsManager(UsernamePasswordCredentialsProvider provider) {
2829
this.provider = provider;
2930
this.registration = new RegistrationImpl(provider);
3031
}

src/main/java/com/rabbitmq/client/amqp/impl/Credentials.java renamed to src/main/java/com/rabbitmq/client/amqp/oauth2/CredentialsManager.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
//
1616
// If you have any questions regarding licensing, please contact us at
1717
18-
package com.rabbitmq.client.amqp.impl;
18+
package com.rabbitmq.client.amqp.oauth2;
1919

20-
interface Credentials {
20+
public interface CredentialsManager {
2121

22-
Credentials NO_OP = new NoOpCredentials();
22+
CredentialsManager NO_OP = new NoOpCredentialsManager();
2323

2424
Registration register(String name, AuthenticationCallback updateCallback);
2525

@@ -35,7 +35,7 @@ interface AuthenticationCallback {
3535
void authenticate(String username, String password);
3636
}
3737

38-
class NoOpCredentials implements Credentials {
38+
class NoOpCredentialsManager implements CredentialsManager {
3939

4040
@Override
4141
public Registration register(String name, AuthenticationCallback updateCallback) {

src/main/java/com/rabbitmq/client/amqp/impl/TokenCredentials.java renamed to src/main/java/com/rabbitmq/client/amqp/oauth2/TokenCredentialsManager.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@
1515
//
1616
// If you have any questions regarding licensing, please contact us at
1717
18-
package com.rabbitmq.client.amqp.impl;
18+
package com.rabbitmq.client.amqp.oauth2;
1919

20-
import com.rabbitmq.client.amqp.oauth2.Token;
21-
import com.rabbitmq.client.amqp.oauth2.TokenRequester;
2220
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
2321
import java.time.Duration;
2422
import java.time.Instant;
@@ -39,11 +37,11 @@
3937
import org.slf4j.Logger;
4038
import org.slf4j.LoggerFactory;
4139

42-
final class TokenCredentials implements Credentials {
40+
public final class TokenCredentialsManager implements CredentialsManager {
4341

44-
static Function<Instant, Duration> DEFAULT_REFRESH_DELAY_STRATEGY =
42+
public static Function<Instant, Duration> DEFAULT_REFRESH_DELAY_STRATEGY =
4543
ratioRefreshDelayStrategy(0.8f);
46-
private static final Logger LOGGER = LoggerFactory.getLogger(TokenCredentials.class);
44+
private static final Logger LOGGER = LoggerFactory.getLogger(TokenCredentialsManager.class);
4745

4846
private final TokenRequester requester;
4947
private final ScheduledExecutorService scheduledExecutorService;
@@ -55,7 +53,7 @@ final class TokenCredentials implements Credentials {
5553
private final Function<Instant, Duration> refreshDelayStrategy;
5654
private volatile ScheduledFuture<?> refreshTask;
5755

58-
TokenCredentials(
56+
public TokenCredentialsManager(
5957
TokenRequester requester,
6058
ScheduledExecutorService scheduledExecutorService,
6159
Function<Instant, Duration> refreshDelayStrategy) {
@@ -81,12 +79,15 @@ private Token getToken() {
8179
LOGGER.debug(
8280
"Requesting new token ({})...", registrationSummary(this.registrations.values()));
8381
}
84-
Utils.StopWatch stopWatch = new Utils.StopWatch();
82+
long start = 0L;
83+
if (LOGGER.isDebugEnabled()) {
84+
start = System.nanoTime();
85+
}
8586
Token token = requester.request();
8687
if (LOGGER.isDebugEnabled()) {
8788
LOGGER.debug(
8889
"Got new token in {} ms, token expires on {} ({})",
89-
stopWatch.stop().toMillis(),
90+
Duration.ofNanos(System.nanoTime() - start),
9091
format(token.expirationTime()),
9192
registrationSummary(this.registrations.values()));
9293
}
@@ -287,7 +288,7 @@ public String toString() {
287288
}
288289
}
289290

290-
static Function<Instant, Duration> ratioRefreshDelayStrategy(float ratio) {
291+
public static Function<Instant, Duration> ratioRefreshDelayStrategy(float ratio) {
291292
return new RatioRefreshDelayStrategy(ratio);
292293
}
293294

src/test/java/com/rabbitmq/client/amqp/impl/Assertions.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import org.apache.qpid.protonj2.types.UnsignedLong;
3131
import org.assertj.core.api.AbstractObjectAssert;
3232

33-
final class Assertions {
33+
public final class Assertions {
3434

3535
private Assertions() {}
3636

@@ -42,7 +42,7 @@ static QueueInfoAssert assertThat(Management.QueueInfo queueInfo) {
4242
return new QueueInfoAssert(queueInfo);
4343
}
4444

45-
static SyncAssert assertThat(TestUtils.Sync sync) {
45+
public static SyncAssert assertThat(TestUtils.Sync sync) {
4646
return new SyncAssert(sync);
4747
}
4848

@@ -83,13 +83,13 @@ CountDownLatchAssert completes(Duration timeout) {
8383
}
8484
}
8585

86-
static class SyncAssert extends AbstractObjectAssert<SyncAssert, TestUtils.Sync> {
86+
public static class SyncAssert extends AbstractObjectAssert<SyncAssert, TestUtils.Sync> {
8787

8888
private SyncAssert(TestUtils.Sync sync) {
8989
super(sync, SyncAssert.class);
9090
}
9191

92-
SyncAssert completes() {
92+
public SyncAssert completes() {
9393
return this.completes(TestUtils.DEFAULT_CONDITION_TIMEOUT);
9494
}
9595

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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.impl;
19+
20+
import com.rabbitmq.client.amqp.Connection;
21+
import com.rabbitmq.client.amqp.Environment;
22+
import com.rabbitmq.client.amqp.Publisher;
23+
import java.util.UUID;
24+
import org.junit.jupiter.api.Test;
25+
26+
public class OAuth2RealTest {
27+
28+
@Test
29+
void test() throws Exception {
30+
String token =
31+
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJHbmwyWmxiUmgzckFyNld5bWM5ODhfNWNZN1Q1R3VlUGQ1ZHBKbFhESlVrIn0.eyJleHAiOjE3MzQ2ODI2MjksImlhdCI6MTczNDY4MjMyOSwianRpIjoiMzg0ZTY2ZTMtOGE4NC00ZmI1LWIyZjAtZDg5NDI4YzcxMjg2IiwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6ODQ0My9yZWFsbXMvdGVzdCIsImF1ZCI6InJhYmJpdG1xIiwic3ViIjoiNTBiMzg0NjQtNDQwYy00OGQyLTg4MGQtMDUwYTdkMjhmN2IwIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicHJvZHVjZXIiLCJzZXNzaW9uX3N0YXRlIjoiOWNjNGNiZGYtYjY4ZS00NTM3LWJjNmMtMmRiOGI3NGY3MGY2IiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtdGVzdCIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InJhYmJpdG1xLnJlYWQ6Ki8qIHJhYmJpdG1xLndyaXRlOiovKiByYWJiaXRtcS5jb25maWd1cmU6Ki8qIiwic2lkIjoiOWNjNGNiZGYtYjY4ZS00NTM3LWJjNmMtMmRiOGI3NGY3MGY2IiwiY2xpZW50SWQiOiJwcm9kdWNlciIsImNsaWVudEhvc3QiOiIxNzIuMjIuMC4xIiwiY2xpZW50QWRkcmVzcyI6IjE3Mi4yMi4wLjEifQ.flIe8YhawDB4Xpp1mxbsAZtwXcaX1OSztZX7QUYmQhbDCtABH7ywAZsgnoIs6zYR1alrxvtCFF9FlHeO1hzK4KW07bba5FX2ttFnd-6Z_9uQQM9YhNH80uRfakQDr6goUSaV2vTY0DqFTMtgQIl7Bj4DFwoGzsfGAeidXpK8uFrZMjc3SONk1LdXA005jXmzjPjcdvfMGHM4RG0Rx9zvonou_SsOaEmbg026jdOlVmVsLljxkkZF5VMTQTfbtEFicPUnmAN4GdCee0gAoDu7LsgFZUWn-t6QDgLmdGtMZPo3zQcaWsKXPtuea7_FcPIO9l25zN6jeE72UwBT3_Io4g";
32+
Environment environment =
33+
new AmqpEnvironmentBuilder()
34+
.connectionSettings()
35+
.oauth2()
36+
.tokenEndpointUri("https://localhost:8443/realms/test/protocol/openid-connect/token")
37+
.clientId("producer")
38+
.clientSecret("kbOFBXI9tANgKUq8vXHLhT6YhbivgXxn")
39+
.tls()
40+
.sslContext(TlsTestUtils.alwaysTrustSslContext())
41+
.oauth2()
42+
.connection()
43+
.environmentBuilder()
44+
.build();
45+
46+
Connection c = environment.connectionBuilder().build();
47+
48+
String q = UUID.randomUUID().toString();
49+
c.management().queue(q).exclusive(true).declare();
50+
51+
c.consumerBuilder().queue(q).messageHandler((ctx, msg) -> ctx.accept()).build();
52+
53+
Publisher p = c.publisherBuilder().queue(q).build();
54+
while (true) {
55+
Thread.sleep(100);
56+
p.publish(p.message(), ctx -> {});
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)