From 7cf728cefcf888233051589cb7c271ee5427e202 Mon Sep 17 00:00:00 2001 From: SravanThotakura05 <83568543+SravanThotakura05@users.noreply.github.com> Date: Wed, 8 May 2024 13:37:11 +0530 Subject: [PATCH 1/6] Removed filter condition when fetching access token. Now access token should be fetched on each interval --- .../com/solace/quarkus/runtime/OidcProvider.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java index 67fd962..3d75d0f 100644 --- a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java +++ b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java @@ -33,6 +33,8 @@ public class OidcProvider { private volatile Tokens lastToken; + private MessagingService service; + Tokens getToken() { OidcClient client = getClient(); Tokens firstToken = client.getTokens().await().indefinitely(); @@ -44,11 +46,14 @@ void init(MessagingService service) { OidcClient client = getClient(); Multi.createFrom().ticks().every(duration) .emitOn(Infrastructure.getDefaultWorkerPool()) - .filter(x -> lastToken == null - || lastToken.getRefreshTokenTimeSkew() == null - || lastToken.isAccessTokenWithinRefreshInterval()) + // .filter(x -> { + // return lastToken == null + // || lastToken.getRefreshTokenTimeSkew() == null + // || lastToken.isAccessTokenWithinRefreshInterval(); + // }) .call(() -> { - if (lastToken != null && lastToken.getRefreshToken() != null) { + if (lastToken != null && lastToken.getRefreshToken() != null + && lastToken.isAccessTokenWithinRefreshInterval()) { Log.info("Refreshing access token for Solace connection"); return client.refreshTokens(lastToken.getRefreshToken()).invoke(tokens -> lastToken = tokens); } else { @@ -64,6 +69,7 @@ void init(MessagingService service) { .subscribe().with(x -> { if (service.isConnected()) { service.updateProperty(SCHEME_OAUTH2_ACCESS_TOKEN, lastToken.getAccessToken()); + Log.info("Updated Solace Session with latest access token"); } else { Log.info("Solace service is not connected, cannot update access token without valid connection"); } @@ -79,4 +85,4 @@ public Tokens getLastToken() { return lastToken; } -} \ No newline at end of file +} From 6736c0c4f00ddc40fcb36a378471e115d1c6adda Mon Sep 17 00:00:00 2001 From: SravanThotakura05 <83568543+SravanThotakura05@users.noreply.github.com> Date: Thu, 9 May 2024 14:35:22 +0530 Subject: [PATCH 2/6] added token update on solace reconnection --- .../com/solace/quarkus/runtime/SolaceRecorder.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/SolaceRecorder.java b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/SolaceRecorder.java index f4bc041..b1cf691 100644 --- a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/SolaceRecorder.java +++ b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/SolaceRecorder.java @@ -1,5 +1,7 @@ package com.solace.quarkus.runtime; +import static com.solace.messaging.config.SolaceProperties.AuthenticationProperties.SCHEME_OAUTH2_ACCESS_TOKEN; + import java.util.Map; import java.util.Properties; import java.util.function.Function; @@ -14,6 +16,7 @@ import com.solace.quarkus.MessagingServiceClientCustomizer; import io.quarkus.arc.SyntheticCreationalContext; +import io.quarkus.logging.Log; import io.quarkus.runtime.ShutdownContext; import io.quarkus.runtime.annotations.Recorder; @@ -71,6 +74,13 @@ public MessagingService apply(SyntheticCreationalContext conte } }); + service.addReconnectionAttemptListener(serviceEvent -> { + Log.info("Reconnecting to Solace broker due to " + serviceEvent.getMessage()); + if (oidcProvider != null && authScheme != null && "AUTHENTICATION_SCHEME_OAUTH2".equals(authScheme)) { + service.updateProperty(SCHEME_OAUTH2_ACCESS_TOKEN, oidcProvider.getToken().getAccessToken()); + } + }); + return service.connect(); } }; From 79718e171d4d2e2553e7e03a711759a4252a99e8 Mon Sep 17 00:00:00 2001 From: SravanThotakura05 <83568543+SravanThotakura05@users.noreply.github.com> Date: Mon, 13 May 2024 20:40:51 +0530 Subject: [PATCH 3/6] Removed filter condition during token refresh and added token update during reconnect attempt. --- .../main/java/com/solace/quarkus/runtime/OidcProvider.java | 6 +----- .../java/com/solace/quarkus/runtime/SolaceRecorder.java | 1 + .../runtime/src/main/resources/META-INF/beans.xml | 0 3 files changed, 2 insertions(+), 5 deletions(-) create mode 100644 quarkus-solace-client/runtime/src/main/resources/META-INF/beans.xml diff --git a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java index 3d75d0f..b0866f6 100644 --- a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java +++ b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java @@ -42,15 +42,11 @@ Tokens getToken() { return firstToken; } + // @Todo Check if refresh interval is required as token is updated during reconnect in SolaceRecorder.java file. Need to be removed after proper analysis of corner cases. void init(MessagingService service) { OidcClient client = getClient(); Multi.createFrom().ticks().every(duration) .emitOn(Infrastructure.getDefaultWorkerPool()) - // .filter(x -> { - // return lastToken == null - // || lastToken.getRefreshTokenTimeSkew() == null - // || lastToken.isAccessTokenWithinRefreshInterval(); - // }) .call(() -> { if (lastToken != null && lastToken.getRefreshToken() != null && lastToken.isAccessTokenWithinRefreshInterval()) { diff --git a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/SolaceRecorder.java b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/SolaceRecorder.java index b1cf691..920df4d 100644 --- a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/SolaceRecorder.java +++ b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/SolaceRecorder.java @@ -74,6 +74,7 @@ public MessagingService apply(SyntheticCreationalContext conte } }); + // Update access token on reconnect to make sure invalid token is not sent. This can happen when a reconnection happens event before scheduled token expiry. service.addReconnectionAttemptListener(serviceEvent -> { Log.info("Reconnecting to Solace broker due to " + serviceEvent.getMessage()); if (oidcProvider != null && authScheme != null && "AUTHENTICATION_SCHEME_OAUTH2".equals(authScheme)) { diff --git a/quarkus-solace-client/runtime/src/main/resources/META-INF/beans.xml b/quarkus-solace-client/runtime/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..e69de29 From 938606b3ed554d93bff792df69e90f77b038e089 Mon Sep 17 00:00:00 2001 From: SravanThotakura05 <83568543+SravanThotakura05@users.noreply.github.com> Date: Mon, 13 May 2024 20:42:33 +0530 Subject: [PATCH 4/6] removed unnecessary variable & method --- .../main/java/com/solace/quarkus/runtime/OidcProvider.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java index b0866f6..4e50e0a 100644 --- a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java +++ b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java @@ -33,8 +33,6 @@ public class OidcProvider { private volatile Tokens lastToken; - private MessagingService service; - Tokens getToken() { OidcClient client = getClient(); Tokens firstToken = client.getTokens().await().indefinitely(); @@ -77,8 +75,4 @@ OidcClient getClient() { .orElseGet(clients::getClient); } - public Tokens getLastToken() { - return lastToken; - } - } From 90de8b1adc6275ac164c4fd1ba7ca2f0e329582a Mon Sep 17 00:00:00 2001 From: SravanThotakura05 <83568543+SravanThotakura05@users.noreply.github.com> Date: Mon, 13 May 2024 20:49:23 +0530 Subject: [PATCH 5/6] Removed unnecessary comment --- .../src/main/java/com/solace/quarkus/runtime/OidcProvider.java | 1 - 1 file changed, 1 deletion(-) diff --git a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java index 4e50e0a..34ea8f8 100644 --- a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java +++ b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java @@ -40,7 +40,6 @@ Tokens getToken() { return firstToken; } - // @Todo Check if refresh interval is required as token is updated during reconnect in SolaceRecorder.java file. Need to be removed after proper analysis of corner cases. void init(MessagingService service) { OidcClient client = getClient(); Multi.createFrom().ticks().every(duration) From 0995bc0d7f8e5a910d8ccedd7e1867b3da501fe3 Mon Sep 17 00:00:00 2001 From: SravanThotakura05 <83568543+SravanThotakura05@users.noreply.github.com> Date: Tue, 14 May 2024 17:56:07 +0530 Subject: [PATCH 6/6] Added token refresh api timeout to avoid buffer overflow of requests. --- docs/modules/ROOT/pages/index.adoc | 2 ++ .../java/com/solace/quarkus/runtime/OidcProvider.java | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index c4f59fa..f224e78 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -123,6 +123,7 @@ quarkus.solace.vpn=default quarkus.solace.authentication.scheme=AUTHENTICATION_SCHEME_OAUTH2 quarkus.solace.oidc.client-name=solace // client name provided in oidc client config below quarkus.solace.oidc.refresh.interval=50s // Refresh interval should be less than access token expiry time. Otherwise extension will fail to update access token in solace session. +quarkus.solace.oidc.refresh.timeout=10s // Token Refresh API timeout. Default is set to 10 seconds. quarkus.oidc-client.solace.auth-server-url=http://localhost:7777/auth/realms/master quarkus.oidc-client.solace.client-id= @@ -142,6 +143,7 @@ quarkus.solace.tls.trust-store-type= quarkus.solace.tls.trust-store-password= quarkus.solace.oidc.client-name=solace // client name provided in oidc client config below quarkus.solace.oidc.refresh.interval=50s // Refresh interval should be less than access token expiry time. Otherwise extension will fail to update access token in solace session. +quarkus.solace.oidc.refresh.timeout=10s // Token Refresh API timeout. Default is set to 10 seconds. quarkus.oidc-client.solace.auth-server-url=http://localhost:7777/auth/realms/master quarkus.oidc-client.solace.client-id= diff --git a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java index 34ea8f8..2bd369d 100644 --- a/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java +++ b/quarkus-solace-client/runtime/src/main/java/com/solace/quarkus/runtime/OidcProvider.java @@ -25,6 +25,9 @@ public class OidcProvider { @ConfigProperty(name = "quarkus.solace.oidc.refresh.interval", defaultValue = "60s") Duration duration; + @ConfigProperty(name = "quarkus.solace.oidc.refresh.timeout", defaultValue = "10s") + Duration refreshTimeout; + @ConfigProperty(name = "quarkus.solace.oidc.client-name") Optional oidcClientName; @@ -43,15 +46,17 @@ Tokens getToken() { void init(MessagingService service) { OidcClient client = getClient(); Multi.createFrom().ticks().every(duration) + .onOverflow().drop() .emitOn(Infrastructure.getDefaultWorkerPool()) .call(() -> { if (lastToken != null && lastToken.getRefreshToken() != null && lastToken.isAccessTokenWithinRefreshInterval()) { Log.info("Refreshing access token for Solace connection"); - return client.refreshTokens(lastToken.getRefreshToken()).invoke(tokens -> lastToken = tokens); + return client.refreshTokens(lastToken.getRefreshToken()).invoke(tokens -> lastToken = tokens).ifNoItem() + .after(refreshTimeout).fail(); } else { Log.info("Acquiring access token for Solace connection"); - return client.getTokens().invoke(tokens -> lastToken = tokens); + return client.getTokens().invoke(tokens -> lastToken = tokens).ifNoItem().after(refreshTimeout).fail(); } }) .onFailure().call(t -> {