You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2013/07/02 00:04:35 UTC

svn commit: r1498718 - in /jena/trunk: jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ jena-fuseki/src/test/java/org/apache/jena/fuseki/

Author: rvesse
Date: Mon Jul  1 22:04:35 2013
New Revision: 1498718

URL: http://svn.apache.org/r1498718
Log:
Rework scoped authenticators to work more sensibly (JENA-480)
Credentials are now scoped to any URI derived from them e.g. credentials for http://example.org also apply to http://example.org/some/path
However longest match applies since we work backwards from the requested URI so if credentials for http://example.org/some/path were present they would be used instead

Added additional tests to validate these changes

Modified:
    jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractCredentialsAuthenticator.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractScopedAuthenticator.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormLogin.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormsAuthenticator.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ScopedAuthenticator.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ServiceAuthenticator.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/SimpleAuthenticator.java
    jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractCredentialsAuthenticator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractCredentialsAuthenticator.java?rev=1498718&r1=1498717&r2=1498718&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractCredentialsAuthenticator.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractCredentialsAuthenticator.java Mon Jul  1 22:04:35 2013
@@ -35,7 +35,7 @@ import org.apache.http.protocol.HttpCont
 public abstract class AbstractCredentialsAuthenticator implements HttpAuthenticator {
 
     @Override
-    public final void apply(AbstractHttpClient client, HttpContext context, URI target) {
+    public void apply(AbstractHttpClient client, HttpContext context, URI target) {
         // TODO Should we allow a user name without a password (or vice versa)?
         if (!this.hasUserName(target) || !this.hasPassword(target)) return;
         

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractScopedAuthenticator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractScopedAuthenticator.java?rev=1498718&r1=1498717&r2=1498718&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractScopedAuthenticator.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/AbstractScopedAuthenticator.java Mon Jul  1 22:04:35 2013
@@ -18,20 +18,121 @@
 package org.apache.jena.atlas.web.auth;
 
 import java.net.URI;
+import java.net.URISyntaxException;
 
 /**
+ * <p>
  * An abstract helper for authenticators which scope credentials to URIs
+ * </p>
+ * <h3>Credentials Scope</h3>
+ * <p>
+ * Note that credentials are not necessarily considered to be exclusively scoped to the exact URI rather they
+ * are scoped to any URI derived from the given URI. For example if you declared
+ * credentials for {@code http://example.org} they would also apply to
+ * {@code http://example.org/some/path/}. When determining credentials the
+ * longest match applies, so in the previous example you could define different
+ * credentials for the two URIs and URIs derived from
+ * {@code http://example.org/some/path/} would prefer the credentials for that
+ * URI over those for {@code http://example.org}
+ * </p>
+ * <p>
+ * Implementations that wish to follow the above scoping policy should make use of the findCredentials method
+ * </p>
+ * @param <T> Type used to store credential information
  */
-public abstract class AbstractScopedAuthenticator extends AbstractCredentialsAuthenticator {
+public abstract class AbstractScopedAuthenticator<T> extends AbstractCredentialsAuthenticator {
+    
+    protected final String getUserName(URI target) {
+        return getUserNameFromCredentials(this.findCredentials(target));
+    }
+    
+    protected final char[] getPassword(URI target) {
+        return getPasswordFromCredentials(this.findCredentials(target));
+    }
 
     @Override
-    protected boolean hasUserName(URI target) {
+    protected final boolean hasUserName(URI target) {
         return this.getUserName(target) != null;
     }
 
     @Override
-    protected boolean hasPassword(URI target) {
+    protected final boolean hasPassword(URI target) {
         return this.getPassword(target) != null;
     }
+    
+    /**
+     * Gets the credentials associated with the exact URI given
+     * <p>
+     * Called from {@link #findCredentials(URI)} as part of the credential lookup process
+     * </p>
+     * @param target Target URI
+     * @return Credentials
+     */
+    protected abstract T getCredentials(URI target);
+    
+    /**
+     * Extract the user name from the given credentials
+     * @param credentials Credentials
+     * @return User Name
+     */
+    protected abstract String getUserNameFromCredentials(T credentials);
+    
+    /**
+     * Extract the password from the given credentials
+     * @param credentials Credentials
+     * @return Password
+     */
+    protected abstract char[] getPasswordFromCredentials(T credentials);
+
+    /**
+     * Finds credentials for the given URI using a longest match approach
+     * @param target
+     * @return
+     */
+    protected final T findCredentials(URI target) {
+        // Try URI as-is to start with
+        T creds = this.getCredentials(target);
 
+        try {
+            // If that fails strip down the URI recursively
+            while (creds == null) {
+                if (target.getFragment() != null) {
+                    // If it has a fragment strip that off
+                    target = new URI(target.getScheme(), target.getUserInfo(), target.getHost(), target.getPort(),
+                            target.getPath(), target.getQuery(), null);
+                } else if (target.getQuery() != null) {
+                    // If it has a query string strip that off
+                    target = new URI(target.getScheme(), target.getUserInfo(), target.getHost(), target.getPort(),
+                            target.getPath(), null, null);
+                } else if (target.getPath() != null) {
+                    // Try and strip off last segment of the path
+                    String currPath = target.getPath();
+                    if (currPath.endsWith("/")) {
+                        currPath = currPath.substring(0, currPath.length() - 1);
+                        if (currPath.length() == 0)
+                            currPath = null;
+                        target = new URI(target.getScheme(), target.getUserInfo(), target.getHost(), target.getPort(), currPath,
+                                null, null);
+                    } else if (currPath.contains("/")) {
+                        currPath = currPath.substring(0, currPath.lastIndexOf('/') + 1);
+                        if (currPath.length() == 0)
+                            currPath = null;
+                        target = new URI(target.getScheme(), target.getUserInfo(), target.getHost(), target.getPort(), currPath,
+                                null, null);
+                    } else {
+                        // If path is non-null it must always contain a /
+                        // otherwise it would be an invalid path
+                        // In this case bail out
+                        return null;
+                    }
+                }
+
+                creds = this.getCredentials(target);
+            }
+            return creds;
+        } catch (URISyntaxException e) {
+            // If we generate a malformed URL then bail out
+            return null;
+        }
+    }
 }
\ No newline at end of file

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormLogin.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormLogin.java?rev=1498718&r1=1498717&r2=1498718&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormLogin.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormLogin.java Mon Jul  1 22:04:35 2013
@@ -23,6 +23,7 @@ import java.util.List;
 
 import org.apache.http.HttpEntity;
 import org.apache.http.NameValuePair;
+import org.apache.http.client.CookieStore;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.message.BasicNameValuePair;
 
@@ -34,6 +35,7 @@ public class FormLogin {
 
     private String loginForm, loginUserField, loginPasswordField, username;
     private char[] password;
+    private CookieStore cookies;
 
     /**
      * Creates new form login credentials
@@ -80,4 +82,39 @@ public class FormLogin {
 
         return new UrlEncodedFormEntity(nvps, "UTF-8");
     }
+
+    /**
+     * Gets whether any cookies are associated with this login
+     * 
+     * @return True if there are cookies, false otherwise
+     */
+    public boolean hasCookies() {
+        return this.cookies != null;
+    }
+
+    /**
+     * Gets cookies associated with this login
+     * 
+     * @return Cookies
+     */
+    public CookieStore getCookies() {
+        return this.cookies;
+    }
+
+    /**
+     * Sets cookies associated with this login
+     * 
+     * @param cookies
+     */
+    public void setCookies(CookieStore cookies) {
+        this.cookies = cookies;
+    }
+
+    /**
+     * Clears cookies associated with login, may be useful if you need to force
+     * a fresh login attempt for any reason.
+     */
+    public void clearCookies() {
+        this.cookies = null;
+    }
 }

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormsAuthenticator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormsAuthenticator.java?rev=1498718&r1=1498717&r2=1498718&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormsAuthenticator.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/FormsAuthenticator.java Mon Jul  1 22:04:35 2013
@@ -36,16 +36,28 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
+ * <p>
  * An authenticator capable of making Form based logins and using cookies to
  * maintain authentication state. Different logins may be used for different
  * services as required.
+ * </p>
+ * <h3>Login Scope</h3>
+ * <p>
+ * Note that logins are not exclusively scoped to the exact URI rather they are
+ * scoped to any URI derived from the given URI. For example if you declared
+ * logins for {@code http://example.org} they would also apply to
+ * {@code http://example.org/some/path/}. When determining credentials the
+ * longest match applies, so in the previous example you could define different
+ * logins for the two URIs and URIs derived from
+ * {@code http://example.org/some/path/} would prefer the login for that URI
+ * over those for {@code http://example.org}
+ * </p>
  * 
  */
-public class FormsAuthenticator implements HttpAuthenticator {
+public class FormsAuthenticator extends AbstractScopedAuthenticator<FormLogin> {
 
     private static final Logger LOG = LoggerFactory.getLogger(FormsAuthenticator.class);
 
-    private Map<URI, CookieStore> cookies = new HashMap<URI, CookieStore>();
     private Map<URI, FormLogin> logins = new HashMap<URI, FormLogin>();
 
     /**
@@ -73,65 +85,67 @@ public class FormsAuthenticator implemen
     }
 
     @Override
-    public synchronized void apply(AbstractHttpClient client, HttpContext httpContext, URI target) {
+    public void apply(AbstractHttpClient client, HttpContext httpContext, URI target) {
         if (client == null)
             return;
 
-        synchronized (this.cookies) {
-            if (this.cookies.containsKey(target)) {
+        // Do we have a login available for the target server?
+        FormLogin login = this.findCredentials(target);
+        if (login == null)
+            return;
+
+        // We need to synchronize on the login because making a login attempt
+        // may take a while and there is no point making multiple login attempts
+        // against the same server
+        synchronized (login) {
+
+            // Have we already logged into this server?
+            if (login.hasCookies()) {
                 // Use existing cookies
                 LOG.info("Using existing cookies to authenticate access to " + target.toString());
-                CookieStore store = this.cookies.get(target);
+                CookieStore store = login.getCookies();
                 if (store != null)
                     client.setCookieStore(store);
                 return;
             }
-        }
 
-        // Do we have a login available for the target server?
-        FormLogin login = this.logins.get(target);
-        if (login == null)
-            return;
+            try {
+                // Use a fresh Cookie Store for new login attempts
+                CookieStore store = new BasicCookieStore();
+                client.setCookieStore(store);
 
-        // Use a fresh Cookie Store for new login attempts
-        CookieStore store = new BasicCookieStore();
-        client.setCookieStore(store);
-
-        try {
-            // Try to login
-            LOG.info("Making login attempt against " + login.getLoginFormURL() + " to obtain authentication for access to "
-                    + target.toString());
-            HttpPost post = new HttpPost(login.getLoginFormURL());
-            post.setEntity(login.getLoginEntity());
-            HttpResponse response = client.execute(post, httpContext);
-
-            // Check for successful login
-            if (response.getStatusLine().getStatusCode() >= 400) {
-                LOG.warn("Failed to login against " + login.getLoginFormURL() + " to obtain authentication for access to "
+                // Try to login
+                LOG.info("Making login attempt against " + login.getLoginFormURL() + " to obtain authentication for access to "
                         + target.toString());
-                throw new HttpException(response.getStatusLine().getStatusCode(), "Login attempt failed - "
-                        + response.getStatusLine().getReasonPhrase());
-            }
-
-            // Otherwise assume a successful login
-            LOG.info("Successfully logged in against " + login.getLoginFormURL() + " and obtained authentication for access to "
-                    + target.toString());
-            synchronized (this.cookies) {
-                this.cookies.put(target, client.getCookieStore());
+                HttpPost post = new HttpPost(login.getLoginFormURL());
+                post.setEntity(login.getLoginEntity());
+                HttpResponse response = client.execute(post, httpContext);
+
+                // Check for successful login
+                if (response.getStatusLine().getStatusCode() >= 400) {
+                    LOG.warn("Failed to login against " + login.getLoginFormURL() + " to obtain authentication for access to "
+                            + target.toString());
+                    throw new HttpException(response.getStatusLine().getStatusCode(), "Login attempt failed - "
+                            + response.getStatusLine().getReasonPhrase());
+                }
+
+                // Otherwise assume a successful login
+                LOG.info("Successfully logged in against " + login.getLoginFormURL()
+                        + " and obtained authentication for access to " + target.toString());
+                login.setCookies(client.getCookieStore());
+
+                // Consume the response to free up the connection
+                EntityUtils.consumeQuietly(response.getEntity());
+            } catch (UnsupportedEncodingException e) {
+                throw new HttpException("UTF-8 encoding not supported on your platform", e);
+            } catch (IOException e) {
+                throw new HttpException("Error making login request", e);
             }
-
-            // Consume the response to free up the connection
-            EntityUtils.consumeQuietly(response.getEntity());
-        } catch (UnsupportedEncodingException e) {
-            throw new HttpException("UTF-8 encoding not supported on your platform", e);
-        } catch (IOException e) {
-            throw new HttpException("Error making login request", e);
         }
     }
 
     /**
-     * Adds a login to the authenticator, if the authenticator had previously
-     * logged into the given URI cookies for that URI are discarded
+     * Adds a login to the authenticator preserving any existing cookies associated with the login
      * 
      * @param target
      *            Target URI
@@ -142,9 +156,26 @@ public class FormsAuthenticator implemen
         if (target == null)
             throw new IllegalArgumentException("Target URI cannot be null");
         this.logins.put(target, login);
-        synchronized (this.cookies) {
-            this.cookies.remove(target);
-        }
+        
+    }
+
+    @Override
+    protected FormLogin getCredentials(URI target) {
+        return this.logins.get(target.toString());
+    }
+
+    @Override
+    protected String getUserNameFromCredentials(FormLogin credentials) {
+        // Not used by this implementation because we override apply() so this
+        // will never be needed and regardless isn't available
+        return null;
+    }
+
+    @Override
+    protected char[] getPasswordFromCredentials(FormLogin credentials) {
+        // Not used by this implementation because we override apply() so this
+        // will never be needed and regardless isn't available
+        return null;
     }
 
 }

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ScopedAuthenticator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ScopedAuthenticator.java?rev=1498718&r1=1498717&r2=1498718&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ScopedAuthenticator.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ScopedAuthenticator.java Mon Jul  1 22:04:35 2013
@@ -25,55 +25,72 @@ import java.util.Map;
 import org.apache.jena.atlas.lib.Pair;
 
 /**
+ * <p>
  * A credentials based authenticator where credentials are scoped to URIs. This
  * allows for a single authenticator to present different credentials to
  * different URIs as appropriate.
+ * </p>
  * 
  */
-public class ScopedAuthenticator extends AbstractScopedAuthenticator {
+public class ScopedAuthenticator extends AbstractScopedAuthenticator<Pair<String, char[]>> {
 
     private Map<URI, Pair<String, char[]>> credentials = new HashMap<URI, Pair<String, char[]>>();
 
     /**
      * Creates an authenticator with credentials for the given URI
-     * @param target URI
-     * @param username User name
-     * @param password Password
+     * 
+     * @param target
+     *            URI
+     * @param username
+     *            User name
+     * @param password
+     *            Password
      */
     public ScopedAuthenticator(URI target, String username, char[] password) {
-        if (target == null) throw new IllegalArgumentException("Target URI cannot be null");
+        if (target == null)
+            throw new IllegalArgumentException("Target URI cannot be null");
         this.credentials.put(target, Pair.create(username, password));
     }
 
     /**
      * Creates an authenticator with a set of credentials for URIs
-     * @param credentials Credentials
+     * 
+     * @param credentials
+     *            Credentials
      */
     public ScopedAuthenticator(Map<URI, Pair<String, char[]>> credentials) {
         this.credentials.putAll(credentials);
     }
-    
+
     /**
      * Adds/Overwrites credentials for a given URI
-     * @param target Target
-     * @param username User name
-     * @param password Password
+     * 
+     * @param target
+     *            Target
+     * @param username
+     *            User name
+     * @param password
+     *            Password
      */
     public void addCredentials(URI target, String username, char[] password) {
-        if (target == null) throw new IllegalArgumentException("Target URI cannot be null");
+        if (target == null)
+            throw new IllegalArgumentException("Target URI cannot be null");
         this.credentials.put(target, Pair.create(username, password));
     }
 
     @Override
-    protected String getUserName(URI target) {
-        Pair<String, char[]> p = this.credentials.get(target);
-        return p != null ? p.getLeft() : null;
+    protected Pair<String, char[]> getCredentials(URI target) {
+        return this.credentials.get(target);
+    }
+
+    @Override
+    protected String getUserNameFromCredentials(Pair<String, char[]> credentials) {
+        return credentials != null ? credentials.getLeft() : null;
     }
 
     @Override
-    protected char[] getPassword(URI target) {
-        Pair<String, char[]> p = this.credentials.get(target);
-        return p != null ? p.getRight() : null;
+    protected char[] getPasswordFromCredentials(Pair<String, char[]> credentials) {
+        return credentials != null ? credentials.getRight() : null;
     }
 
 }

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ServiceAuthenticator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ServiceAuthenticator.java?rev=1498718&r1=1498717&r2=1498718&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ServiceAuthenticator.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/ServiceAuthenticator.java Mon Jul  1 22:04:35 2013
@@ -26,13 +26,14 @@ import com.hp.hpl.jena.sparql.engine.htt
 import com.hp.hpl.jena.sparql.util.Context;
 
 /**
+ * <p>
  * A HTTP authenticator which selects credentials based upon service context
  * found in the provided {@link Context}. May also optionally use fallback
  * credentials for URIs for which authentication has not been explicitly
  * configured.
- * 
+ * </p> 
  */
-public class ServiceAuthenticator extends AbstractScopedAuthenticator {
+public class ServiceAuthenticator extends AbstractScopedAuthenticator<Context> {
 
     private Context context;
     private String username;
@@ -87,42 +88,40 @@ public class ServiceAuthenticator extend
         this.password = password;
     }
 
+    @SuppressWarnings("unchecked")
+    private Map<String, Context> getServiceContextMap() {
+        return (Map<String, Context>) this.context.get(Service.serviceContext);
+
+    }
+
     @Override
-    public String getUserName(URI target) {
-        if (this.context != null) {
+    protected Context getCredentials(URI target) {
+        Map<String, Context> serviceContextMap = this.getServiceContextMap();
+        if (serviceContextMap == null)
+            return null;
+        return serviceContextMap.get(target.toString());
+    }
 
-            @SuppressWarnings("unchecked")
-            Map<String, Context> serviceContextMap = (Map<String, Context>) this.context.get(Service.serviceContext);
-            if (serviceContextMap != null && serviceContextMap.containsKey(target.toString())) {
-                // Try to obtain Context for target URI
-                Context serviceContext = serviceContextMap.get(target.toString());
-                if (serviceContext != null) {
-                    // Service Context exists for target URI
-                    return serviceContext.getAsString(Service.queryAuthUser);
-                }
-            }
+    @Override
+    protected String getUserNameFromCredentials(Context credentials) {
+        if (credentials != null) {
+            // Use user name from service context
+            return credentials.getAsString(Service.queryAuthUser);
+        } else {
+            // Use fallback user name
+            return this.username;
         }
-        // Use fallback user name
-        return this.username;
     }
 
     @Override
-    public char[] getPassword(URI target) {
-        if (this.context != null) {
-
-            @SuppressWarnings("unchecked")
-            Map<String, Context> serviceContextMap = (Map<String, Context>) this.context.get(Service.serviceContext);
-            if (serviceContextMap != null && serviceContextMap.containsKey(target.toString())) {
-                // Try to obtain Context for target URI
-                Context serviceContext = serviceContextMap.get(target.toString());
-                if (serviceContext != null) {
-                    // Service Context exists for target URI
-                    String pwd = serviceContext.getAsString(Service.queryAuthPwd);
-                    return pwd != null ? pwd.toCharArray() : null;
-                }
-            }
+    protected char[] getPasswordFromCredentials(Context credentials) {
+        if (credentials != null) {
+            // Use password from service context
+            String pwd = credentials.getAsString(Service.queryAuthPwd);
+            return pwd != null ? pwd.toCharArray() : null;
+        } else {
+            // Use fallback password
+            return this.password;
         }
-        // User fallback password
-        return this.password;
     }
 }

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/SimpleAuthenticator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/SimpleAuthenticator.java?rev=1498718&r1=1498717&r2=1498718&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/SimpleAuthenticator.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/web/auth/SimpleAuthenticator.java Mon Jul  1 22:04:35 2013
@@ -21,9 +21,11 @@ package org.apache.jena.atlas.web.auth;
 import java.net.URI;
 
 /**
+ * <p>
  * A HTTP Authenticator which provides authentication via user name and password
  * combinations, can in principal be used to authenticate with any of the HTTP
  * authentication schemes that HTTP Client supports
+ * </p>
  * <p>
  * This authenticator will presents the given credentials to any server, it is
  * typically more secure to use the {@link ScopedAuthenticator} instead.

Modified: jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java?rev=1498718&r1=1498717&r2=1498718&view=diff
==============================================================================
--- jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java (original)
+++ jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java Mon Jul  1 22:04:35 2013
@@ -219,6 +219,29 @@ public class TestAuth extends ServerTest
     
     @Test
     public void query_with_auth_11() {
+        Context ctx = ARQ.getContext();
+        try {
+            QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+            // Auth credentials for valid user with correct password and scoped
+            // to base URI of the actual service URL
+            // Provided via Service Context and its associated authenticator
+            Map<String, Context> serviceContext = new HashMap<String, Context>();
+            Context authContext = new Context();
+            authContext.put(Service.queryAuthUser, "allowed");
+            authContext.put(Service.queryAuthPwd, "password");
+            serviceContext.put(urlRoot, authContext);
+            ctx.put(Service.serviceContext, serviceContext);
+
+            qe.setAuthenticator(new ServiceAuthenticator());
+            Assert.assertTrue(qe.execAsk());
+        } finally {
+            ctx.remove(Service.serviceContext);
+        }
+    }
+    
+    @Test
+    public void query_with_auth_12() {
         ARQ.getContext().remove(Service.serviceContext);
 
         QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
@@ -228,6 +251,28 @@ public class TestAuth extends ServerTest
         qe.setAuthenticator(new ServiceAuthenticator("allowed", "password".toCharArray()));
         Assert.assertTrue(qe.execAsk());
      }
+    
+    @Test
+    public void query_with_auth_13() throws URISyntaxException {
+        QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+        // Auth credentials for valid user with correct password and scoped to
+        // base URI of the actual service URL
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(urlRoot), "allowed", "password".toCharArray());
+        qe.setAuthenticator(authenticator);
+        Assert.assertTrue(qe.execAsk());
+    }
+    
+    @Test
+    public void query_with_auth_14() throws URISyntaxException {
+        QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+        // Auth credentials for valid user with correct password and scoped to
+        // base URI of the actual service URL
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI("http://localhost:" + port), "allowed", "password".toCharArray());
+        qe.setAuthenticator(authenticator);
+        Assert.assertTrue(qe.execAsk());
+    }
 
     @Test(expected = HttpException.class)
     public void update_with_auth_01() {
@@ -368,10 +413,7 @@ public class TestAuth extends ServerTest
         accessor.getModel();
     }
     
-    //TODO Currently broken because scoped authenticators aren't taking into account derived URIs which seems like a sensible enhancement
-    
     @Test
-    @Ignore
     public void graphstore_with_auth_05() throws URISyntaxException {
         // Correct auth credentials scoped to correct URI
         DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new ScopedAuthenticator(new URI(serviceREST), "allowed", "password".toCharArray()));