[java-idp-plugin-duo] branch main updated: JDUO-92 - Update duo_universal_java to version 1.2.0
Phil Smart
philip.smart at jisc.ac.uk
Fri Mar 21 17:16:17 UTC 2025
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch main
in repository java-idp-plugin-duo.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-duo.git;a=commit;h=4fa6c428d047b7d58000002a3e525ebb3ea830d6
The following commit(s) were added to refs/heads/main by this push:
new 4fa6c428 JDUO-92 - Update duo_universal_java to version 1.2.0
4fa6c428 is described below
commit 4fa6c428d047b7d58000002a3e525ebb3ea830d6
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Mar 21 17:16:15 2025 +0000
JDUO-92 - Update duo_universal_java to version 1.2.0
- Expose HTTP proxy port and hostname for the Duo SDK variant
https://shibboleth.atlassian.net/browse/JDUO-92
---
.../authn/duo/sdk/impl/DuoSDKClientAdaptor.java | 98 ++++++++++++++++------
.../authn/duo/sdk/impl/DuoSDKClientFactory.java | 66 ++++++++++++++-
.../plugin/authn/duo/duo-client-factory-bean.xml | 4 +-
.../authn/duo/sdk/conf/authn/duo-oidc.properties | 4 +
4 files changed, 145 insertions(+), 27 deletions(-)
diff --git a/idp-duo-sdk-client-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/sdk/impl/DuoSDKClientAdaptor.java b/idp-duo-sdk-client-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/sdk/impl/DuoSDKClientAdaptor.java
index 53d10350..49a66e58 100644
--- a/idp-duo-sdk-client-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/sdk/impl/DuoSDKClientAdaptor.java
+++ b/idp-duo-sdk-client-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/sdk/impl/DuoSDKClientAdaptor.java
@@ -90,32 +90,82 @@ public final class DuoSDKClientAdaptor extends AbstractDuoOIDCClient{
*/
DuoSDKClientAdaptor(@Nonnull final DuoOIDCIntegration integration,
@Nullable final List<String> caCerts) throws DuoClientException {
- super();
- duoIntegration = Constraint.isNotNull(integration,"Duo SDK Client requires a non-null Duo Integration");
- healthCheckResponseConverter = new DefaultHealthCheckResponseConverter();
- tokenResponseConverter = new DefaultTokenResponseConverter();
+ super();
+ duoIntegration = Constraint.isNotNull(integration,"Duo SDK Client requires a non-null Duo Integration");
+ healthCheckResponseConverter = new DefaultHealthCheckResponseConverter();
+ tokenResponseConverter = new DefaultTokenResponseConverter();
- try {
- if (caCerts == null) {
- //will use the default certs in the Client if the caCerts are null
- final Client newClient = new Client.Builder(integration.getClientId(), integration.getSecretKey(),
- integration.getAPIHost(), integration.getRedirectURI()).setUseDuoCodeAttribute(false).build();
- assert newClient != null;
- client = newClient;
- } else {
- final Client newClient = new Client.Builder(integration.getClientId(), integration.getSecretKey(),
- integration.getAPIHost(), integration.getRedirectURI()).setCACerts(
- caCerts.toArray(new String[caCerts.size()]))
- .setUseDuoCodeAttribute(false).build();
- assert newClient != null;
- client = newClient;
- }
- } catch (final DuoException e) {
- //wrap exception and throw
- throw new DuoClientException(e);
- }
-
+ try {
+ if (caCerts == null) {
+ //will use the default certs in the Client if the caCerts are null
+ final Client newClient = new Client.Builder(integration.getClientId(), integration.getSecretKey(),
+ integration.getAPIHost(), integration.getRedirectURI())
+ .setUseDuoCodeAttribute(false)
+ .build();
+ assert newClient != null;
+ client = newClient;
+ } else {
+ final Client newClient = new Client.Builder(integration.getClientId(), integration.getSecretKey(),
+ integration.getAPIHost(), integration.getRedirectURI()).setCACerts(
+ caCerts.toArray(new String[caCerts.size()]))
+ .setUseDuoCodeAttribute(false)
+ .build();
+ assert newClient != null;
+ client = newClient;
+ }
+ } catch (final DuoException e) {
+ //wrap exception and throw
+ throw new DuoClientException(e);
+ }
}
+
+ /**
+ *
+ * Package-private constructor. Initialises the native Duo SDK client.
+ *
+ * <p>Should only be instantiated by the {@link DuoSDKClientFactory}.</p>
+ *
+ * @param integration the Duo integration to initialize the client from. Never {@code null}.
+ * @param caCerts the list of CA Certificates used to validate connections to Duo. Can be {@code null}.
+ * @param proxyHost the HTTP proxy host.
+ * @param proxyPort the HTTP proxy port.
+ *
+ * @throws DuoClientException if there is an error instantiating the client
+ *
+ * @since 2.2.0
+ */
+ DuoSDKClientAdaptor(@Nonnull final DuoOIDCIntegration integration,
+ @Nullable final List<String> caCerts, @Nonnull @NotEmpty final String proxyHost,
+ @Nonnull final Integer proxyPort) throws DuoClientException {
+ super();
+ duoIntegration = Constraint.isNotNull(integration,"Duo SDK Client requires a non-null Duo Integration");
+ healthCheckResponseConverter = new DefaultHealthCheckResponseConverter();
+ tokenResponseConverter = new DefaultTokenResponseConverter();
+
+ try {
+ if (caCerts == null) {
+ //will use the default certs in the Client if the caCerts are null
+ final Client newClient = new Client.Builder(integration.getClientId(), integration.getSecretKey(),
+ integration.getAPIHost(), proxyPort, proxyHost, integration.getRedirectURI())
+ .setUseDuoCodeAttribute(false)
+ .build();
+ assert newClient != null;
+ client = newClient;
+ } else {
+ final Client newClient = new Client.Builder(integration.getClientId(), integration.getSecretKey(),
+ integration.getAPIHost(), proxyPort, proxyHost, integration.getRedirectURI()).setCACerts(
+ caCerts.toArray(new String[caCerts.size()]))
+ .setUseDuoCodeAttribute(false)
+ .build();
+ assert newClient != null;
+ client = newClient;
+ }
+ } catch (final DuoException e) {
+ //wrap exception and throw
+ throw new DuoClientException(e);
+ }
+
+ }
/** {@inheritDoc} */
diff --git a/idp-duo-sdk-client-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/sdk/impl/DuoSDKClientFactory.java b/idp-duo-sdk-client-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/sdk/impl/DuoSDKClientFactory.java
index 1b1c6e24..d5a4d3f7 100644
--- a/idp-duo-sdk-client-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/sdk/impl/DuoSDKClientFactory.java
+++ b/idp-duo-sdk-client-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/sdk/impl/DuoSDKClientFactory.java
@@ -26,6 +26,7 @@ import net.shibboleth.idp.plugin.authn.duo.DuoOIDCClient;
import net.shibboleth.idp.plugin.authn.duo.DuoOIDCClientFactory;
import net.shibboleth.idp.plugin.authn.duo.DuoOIDCIntegration;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.annotation.constraint.Unmodifiable;
import net.shibboleth.shared.component.AbstractInitializableComponent;
import net.shibboleth.shared.primitive.StringSupport;
@@ -38,6 +39,12 @@ public final class DuoSDKClientFactory extends AbstractInitializableComponent im
/** List of CA Certificate pins. If null, the client's default set are used.*/
@GuardedBy("this") @Nullable @NonnullElements @Unmodifiable private List<String> caCerts;
+
+ /** The optional HTTP proxy hostname.*/
+ @GuardedBy("this") @Nullable @NotEmpty private String proxyHost;
+
+ /** The optional HTTP proxy port number.*/
+ @GuardedBy("this") @Nullable private Integer proxyPort;
/**
* Sets the list of CA certificate pins used to verify the Duo client connection
@@ -63,14 +70,69 @@ public final class DuoSDKClientFactory extends AbstractInitializableComponent im
* @return the caCerts.
*/
@Nullable @NonnullElements @Unmodifiable private synchronized List<String> getCaCerts(){
+ checkComponentActive();
return caCerts;
}
-
+
+ /**
+ * Set the HTTP proxy host, guarded by this objects monitor.
+ *
+ * @param proxyHost the proxy host to set.
+ *
+ * @since 2.2.0
+ */
+ public synchronized void setProxyHost(@Nullable @NotEmpty final String host) {
+ checkSetterPreconditions();
+ proxyHost = host;
+ }
+
+ /**
+ * Get the HTTP proxy host, guarded by this objects monitor.
+ *
+ * @return the proxy host.
+ *
+ * @since 2.2.0
+ */
+ @Nullable @NotEmpty private synchronized String getProxyHost() {
+ checkComponentActive();
+ return proxyHost;
+ }
+
+ /**
+ * Set the HTTP proxy port, guarded by this objects monitor.
+ *
+ * @param proxyPort the proxy port to set.
+ *
+ * @since 2.2.0
+ */
+ public synchronized void setProxyPort(@Nullable final Integer port) {
+ checkSetterPreconditions();
+ this.proxyPort = port;
+ }
+
+ /**
+ * Get the HTTP proxy port, guarded by this objects monitor.
+ *
+ * @return the proxy port.
+ *
+ * @since 2.2.0
+ */
+ @Nullable private synchronized Integer getProxyPort() {
+ checkComponentActive();
+ return proxyPort;
+ }
+
@Override
@Nonnull public DuoOIDCClient createInstance(@Nonnull final DuoOIDCIntegration integration)
throws DuoClientException {
//every integration shares the same list of caCert pins.
- return new DuoSDKClientAdaptor(integration, getCaCerts());
+ final var localProxyHost = StringSupport.trimOrNull(getProxyHost());
+ final var localProxyPort = getProxyPort();
+ if (localProxyPort != null && localProxyHost != null) {
+ return new DuoSDKClientAdaptor(integration, getCaCerts(), localProxyHost, localProxyPort);
+ } else {
+ return new DuoSDKClientAdaptor(integration, getCaCerts());
+ }
}
}
diff --git a/idp-duo-sdk-client-impl/src/main/resources/net/shibboleth/idp/plugin/authn/duo/duo-client-factory-bean.xml b/idp-duo-sdk-client-impl/src/main/resources/net/shibboleth/idp/plugin/authn/duo/duo-client-factory-bean.xml
index a8d1600c..69c1d883 100644
--- a/idp-duo-sdk-client-impl/src/main/resources/net/shibboleth/idp/plugin/authn/duo/duo-client-factory-bean.xml
+++ b/idp-duo-sdk-client-impl/src/main/resources/net/shibboleth/idp/plugin/authn/duo/duo-client-factory-bean.xml
@@ -12,7 +12,9 @@
<!-- Client factory with is own unique ID but common (default) alias/name -->
<bean id="shibboleth.authn.DuoOIDC.sdk.clientFactory" name="shibboleth.authn.DuoOIDC.clientFactory"
class="net.shibboleth.idp.plugin.authn.duo.sdk.impl.DuoSDKClientFactory" scope="singleton"
- p:caCerts="#{getObject('shibboleth.authn.DuoOIDC.sdk.TrustedCertificates') ?: getObject('shibboleth.authn.DuoOIDC.sdk.DefaultTrustedCertificates')}">
+ p:caCerts="#{getObject('shibboleth.authn.DuoOIDC.sdk.TrustedCertificates') ?: getObject('shibboleth.authn.DuoOIDC.sdk.DefaultTrustedCertificates')}"
+ p:proxyPort="%{idp.duo.oidc.http.proxy.port:#{null}}"
+ p:proxyHost="%{idp.duo.oidc.http.proxy.host:#{null}}">
</bean>
diff --git a/idp-duo-sdk-client-impl/src/main/resources/net/shibboleth/idp/plugin/authn/duo/sdk/conf/authn/duo-oidc.properties b/idp-duo-sdk-client-impl/src/main/resources/net/shibboleth/idp/plugin/authn/duo/sdk/conf/authn/duo-oidc.properties
index 0de63343..39aa0725 100644
--- a/idp-duo-sdk-client-impl/src/main/resources/net/shibboleth/idp/plugin/authn/duo/sdk/conf/authn/duo-oidc.properties
+++ b/idp-duo-sdk-client-impl/src/main/resources/net/shibboleth/idp/plugin/authn/duo/sdk/conf/authn/duo-oidc.properties
@@ -21,6 +21,10 @@ idp.duo.oidc.redirectURL = https://<hostname>:<port>/idp/profile/Authn/Duo/2FA/d
# We suggest defining this in credentials/secrets.properties
#idp.duo.oidc.secretKey = key
+# HTTP Proxy settings for Duo's HTTP client
+#idp.duo.oidc.http.proxy.port =
+#idp.duo.oidc.http.proxy.host =
+
## Enable the Duo health check for every 2FA request. Defaults to true to tightly follow
## the Duo described workflow. However, it is not *strictly* required.
#idp.duo.oidc.healthcheck.enabled=true
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list