[java-opensaml] branch main updated: OSJ-384 - HTTP client changes to allow for preemptive basic auth

Scott Cantor cantor.2 at osu.edu
Mon Jul 24 15:25:20 UTC 2023


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository java-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=c91eb3a4f9e32b2fd9a45e482d6b88a6952cf98c

The following commit(s) were added to refs/heads/main by this push:
     new c91eb3a4f OSJ-384 - HTTP client changes to allow for preemptive basic auth
c91eb3a4f is described below

commit c91eb3a4f9e32b2fd9a45e482d6b88a6952cf98c
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Jul 24 11:24:50 2023 -0400

    OSJ-384 - HTTP client changes to allow for preemptive basic auth
    
    https://shibboleth.atlassian.net/browse/OSJ-384
    
    Add new context builder APIs to allow for preemptive basic-auth.
    Retrofitted change to HTTP metrics reporter and metadata resolvers.
---
 .../opensaml/core/metrics/impl/HTTPReporter.java   |  5 ++-
 .../impl/AbstractDynamicHTTPMetadataResolver.java  |  7 ++--
 .../resolver/impl/HTTPMetadataResolver.java        |  5 ++-
 .../httpclient/HttpClientSecurityParameters.java   | 38 ++++++++++++++++++++++
 .../httpclient/HttpClientSecuritySupport.java      | 33 +++++++++++++++++++
 5 files changed, 77 insertions(+), 11 deletions(-)

diff --git a/opensaml-core-impl/src/main/java/org/opensaml/core/metrics/impl/HTTPReporter.java b/opensaml-core-impl/src/main/java/org/opensaml/core/metrics/impl/HTTPReporter.java
index d7d105524..d20ef3afc 100644
--- a/opensaml-core-impl/src/main/java/org/opensaml/core/metrics/impl/HTTPReporter.java
+++ b/opensaml-core-impl/src/main/java/org/opensaml/core/metrics/impl/HTTPReporter.java
@@ -60,7 +60,6 @@ import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.component.InitializableComponent;
 import net.shibboleth.shared.component.UninitializedComponentException;
-import net.shibboleth.shared.httpclient.HttpClientSupport;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.primitive.StringSupport;
@@ -297,8 +296,8 @@ public class HTTPReporter extends ScheduledReporter implements InitializableComp
      * @return the client context instance
      */
     @Nonnull private HttpClientContext buildHttpContext(@Nonnull final HttpRequest request) {
-        final HttpClientContext clientContext = HttpClientSupport.buildHttpClientContext();
-        HttpClientSecuritySupport.marshalSecurityParameters(clientContext, httpClientSecurityParameters, false);
+        final HttpClientContext clientContext =
+                HttpClientSecuritySupport.buildHttpClientContext(httpClientSecurityParameters);
         HttpClientSecuritySupport.addDefaultTLSTrustEngineCriteria(clientContext, request);
         return clientContext;
     }
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/metadata/resolver/impl/AbstractDynamicHTTPMetadataResolver.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/metadata/resolver/impl/AbstractDynamicHTTPMetadataResolver.java
index 93ddbf0a6..49f9b094c 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/metadata/resolver/impl/AbstractDynamicHTTPMetadataResolver.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/metadata/resolver/impl/AbstractDynamicHTTPMetadataResolver.java
@@ -318,12 +318,9 @@ public abstract class AbstractDynamicHTTPMetadataResolver extends AbstractDynami
      * @return a new instance of {@link HttpClientContext}
      */
     @Nonnull protected HttpClientContext buildHttpClientContext(@Nonnull final ClassicHttpRequest request) {
-        final HttpClientContext context = HttpClientContext.create();
-        assert context != null;
-        
-        HttpClientSecuritySupport.marshalSecurityParameters(context, httpClientSecurityParameters, true);
+        final HttpClientContext context =
+                HttpClientSecuritySupport.buildHttpClientContext(httpClientSecurityParameters);
         HttpClientSecuritySupport.addDefaultTLSTrustEngineCriteria(context, request);
-        
         return context;
     }
     
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/metadata/resolver/impl/HTTPMetadataResolver.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/metadata/resolver/impl/HTTPMetadataResolver.java
index b43a8882d..822532c71 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/metadata/resolver/impl/HTTPMetadataResolver.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/metadata/resolver/impl/HTTPMetadataResolver.java
@@ -271,10 +271,9 @@ public class HTTPMetadataResolver extends AbstractReloadingMetadataResolver impl
      * @return a new instance of {@link HttpClientContext}
      */
     @Nonnull protected HttpClientContext buildHttpClientContext(@Nonnull final ClassicHttpRequest request) {
-        final HttpClientContext context = HttpClientContext.create();
-        assert context != null;
+        final HttpClientContext context =
+                HttpClientSecuritySupport.buildHttpClientContext(httpClientSecurityParameters);
         
-        HttpClientSecuritySupport.marshalSecurityParameters(context, httpClientSecurityParameters, true);
         HttpClientSecuritySupport.addDefaultTLSTrustEngineCriteria(context, request);
         
         return context;
diff --git a/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityParameters.java b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityParameters.java
index 4517530bd..42c79dc45 100644
--- a/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityParameters.java
+++ b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityParameters.java
@@ -20,11 +20,15 @@ package org.opensaml.security.httpclient;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.net.ssl.HostnameVerifier;
 
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.primitive.StringSupport;
 import net.shibboleth.shared.resolver.CriteriaSet;
 
@@ -33,6 +37,8 @@ import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.HttpHost;
 import org.opensaml.security.trust.TrustEngine;
 import org.opensaml.security.x509.X509Credential;
 
@@ -44,6 +50,9 @@ public class HttpClientSecurityParameters {
     /** HttpClient credentials provider. */
     @Nullable private CredentialsProvider credentialsProvider;
     
+    /** Map of host specifications to basic-auth credentials to be applied preemptively. */
+    @Nullable private Map<HttpHost,UsernamePasswordCredentials> preemptiveBasicAuthMap;
+    
     /** HttpClient {@link AuthCache} to allow pre-emptive authentication. */
     @Nullable private AuthCache authCache;
     
@@ -90,6 +99,35 @@ public class HttpClientSecurityParameters {
         return this;
     }
     
+    /**
+     * Install a map of rules for preemptive basic authentication using the supplied hosts and credentials.
+     * 
+     * <p>Use of this feature requires that the eventual {@link HttpClientContext} used be built using
+     * {@link HttpClientSecuritySupport#buildHttpClientContext(HttpClientSecurityParameters)}.</p>
+     * 
+     * @param map preemptive basic-auth map
+     * 
+     * @return this object
+     * 
+     * @since 5.0.0
+     */
+    @Nonnull public HttpClientSecurityParameters setPreemptiveBasicAuthMap(
+            @Nullable final Map<HttpHost,UsernamePasswordCredentials> map) {
+        preemptiveBasicAuthMap = map != null ? CollectionSupport.copyToMap(map) : null;
+        return this;
+    }
+    
+    /**
+     * Get the map of rules for preemptive basic authentication using the supplied hosts and credentials.
+     * 
+     * @return basic-auth rule map or null
+     * 
+     * @since 5.0.0
+     */
+    @Nullable @Unmodifiable @NotLive public Map<HttpHost,UsernamePasswordCredentials> getPreemptiveBasicAuthMap() {
+        return preemptiveBasicAuthMap;
+    }
+    
     /**
      * Get an instance of {@link AuthCache} used for authentication by the HttpClient instance.
      * 
diff --git a/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecuritySupport.java b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecuritySupport.java
index 0d6e3b0fb..ee1a342d5 100644
--- a/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecuritySupport.java
+++ b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecuritySupport.java
@@ -27,12 +27,16 @@ import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTE
 import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTEXT_KEY_SERVER_TLS_FAILURE_IS_FATAL;
 
 import java.net.URISyntaxException;
+import java.util.Map;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.net.ssl.SSLPeerUnverifiedException;
 
+import org.apache.hc.client5.http.ContextBuilder;
+import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.HttpRequest;
 import org.opensaml.core.config.ConfigurationService;
 import org.opensaml.security.credential.UsageType;
@@ -119,6 +123,35 @@ public final class HttpClientSecuritySupport {
         }
     }
     
+    /**
+     * Builds a new {@link HttpClientContext} and marshals the supplied {@link HttpClientSecurityParameters}
+     * into it.
+     * 
+     * @param securityParameters the parameters to apply to the context
+     * 
+     * @return the fresh context
+     * 
+     * @since 5.0.0
+     */
+    @Nonnull public static HttpClientContext buildHttpClientContext(
+            @Nullable final HttpClientSecurityParameters securityParameters) {
+        final ContextBuilder builder = ContextBuilder.create();
+        
+        if (securityParameters != null) {
+            final Map<HttpHost,UsernamePasswordCredentials> basicAuthMap =
+                    securityParameters.getPreemptiveBasicAuthMap();
+            if (basicAuthMap != null) {
+                basicAuthMap.forEach(builder::preemptiveBasicAuth);
+            }
+        }
+        
+        final HttpClientContext context = builder.build();
+        assert context != null;
+        
+        marshalSecurityParameters(context, securityParameters, true);
+        return context;
+    }
+    
     /**
      * Marshal the supplied {@link HttpClientSecurityParameters} to the supplied {@link HttpClientContext}.
      * 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list