I added simple basic auth support to Fuseki and wrote unit tests that verified that authentication is working correctly.
It would be useful to know what error code/messages you get with the latest SNAPSHOTs? Is there any HTTP proxying/redirection involved in your setup? The applyAuthentication() code scopes provided credentials to the given service URI so if the server is responding with a 401 Unauthorized on a different URI then the original request then HTTP Client may be failing to attempt to pass any credentials at all in response to the servers challenge and simply bailing out and throwing up the 401 error Rob On 6/25/13 2:44 AM, "Arthur Vaïsse-Lesteven" <[email protected]> wrote: > >Hi again. > >It seems that the bug is still present. The HTTPheader not contains >basicAuthentification informations. What test did you do about the new >httpOp ? I may doing it in a wrong way :/ > >After the debugged applyAuthentication in HttpOp, there is the following >line : "HttpResponse response = httpclient.execute(httppost, >httpContext);" > >And I think that the HttpClient.execute method doesn't use the >authentication information available in his Credential provider. > >Rob : "Don't forget you can always check out and do a mvn install locally" >Ho yes, I'll do that next time! > >VAÏSSE-LESTEVEN Arthur. > > >>Hmmm, that is a little weird >> >>I just forced a rebuild and the latest build does have the change in it, >>not sure what happened there. Sometimes the Apache build servers are >>just a little flaky. >> >>Don't forget you can always check out and do a mvn install locally >> >>Rob >> >>From: Arthur Vaïsse-Lesteven >><[email protected]<mailto:[email protected]>> >>Reply-To: "[email protected]<mailto:[email protected]>" >><[email protected]<mailto:[email protected]>>, Arthur >>Vaïsse-Lesteven <[email protected]<mailto:[email protected]>> >>Date: Monday, June 24, 2013 5:26 AM >>To: "[email protected]<mailto:[email protected]>" >><[email protected]<mailto:[email protected]>> >>Subject: Re: Tr : Basic Authentication for SPARQL Update >> >>Hi Rob, >> >>It's a little confusing. >> >>You modified the HttpOp class in the release number 34 on the maven repo >>[1], but this modification isn't present in the last version ( 38 ) as >>you can see in the java file joined to this mail. >> >>The add of "client.setCredentialsProvider(provider);" line 400 probably >>solve the problem but I'm not able to test it as it isn't present in the >>last released version of ARQ. >> >>( The trunk version of your SVN seems to contains this code too ). >> >>Thanks for your work. >> >>VAISSE-LESTEVEN Arthur. >> >> >>[1] >>https://repository.apache.org/content/repositories/snapshots/org/apache/j >>ena/jena-arq/2.10.2-SNAPSHOT/ >>________________________________ >>De : Rob Vesse <[email protected]<mailto:[email protected]>> >>À : "[email protected]<mailto:[email protected]>" >><[email protected]<mailto:[email protected]>> >>Envoyé le : Vendredi 21 juin 2013 19h35 >>Objet : Re: Tr : Basic Authentication for SPARQL Update >> >>The latest SNAPSHOTS now have the fix, you may need to add -U to your mvn >>calls if you have recently updated SNAPSHOTs to get the very latest >> >>Please test and confirm whether this resolves the issue >> >>Rob >> >> >>On 6/21/13 9:13 AM, "Rob Vesse" >><[email protected]<mailto:[email protected]>> wrote: >> >>>Nice catch >>> >>>Yes I appear to have made an error, I never associated the created >>>credentials provider with the HTTP Client >>> >>>Filed as JENA-475 (https://issues.apache.org/jira/browse/JENA-475) >>> >>>I will commit a fix ASAP and you should be able to pick up a >>>2.10.2-SNAPSHOT build in a few hours with the fix, if you can test with >>>the snapshot and report if this resolves the issue that would be great. >>> >>>You can verify whether the fix has gone into the snapshots by looking at >>>https://builds.apache.org/job/Jena__Development_Test/changes and seeing >>>if >>>there is a build listed where the commit messages mention JENA-475 >>> >>>Rob >>> >>> >>> >>>On 6/20/13 11:51 PM, "Arthur Vaïsse-Lesteven" >>><[email protected]<mailto:[email protected]>> >>>wrote: >>> >>>>Hi Rob, I'm in trouble with the basic authentication process ( I'm now >>>>using ARQ 2.10.1 ) >>>> >>>> >>>>In one hand the Queries work like this : >>>>when we calls one of the 4 method execX of a queryExecution, the >>>>QueryEngineHTTP calls makeHttpQuery, and after few steps this code line >>>>is executed : >>>> httpConnection.setRequestProperty("Authorization", "Basic "+y) ; >>>>where y contains userName:password 64Bits encrypted. >>>> >>>>This make the http request header contains the Key, Value couple : >>>>"Authorization" "Basic username:password". >>>> >>>>I'm OK with this. >>>> >>>>In the other hand, the update seem to handle Basic Authentication in a >>>>different way. >>>> >>>>I used this code : >>>> >>>>UpdateRequest update = >>>> UpdateFactory.create(queryString); >>>>UpdateProcessRemoteForm exec = (UpdateProcessRemoteForm) >>>>UpdateExecutionFactory.createRemoteForm(update, service); >>>>exec.setAuthentication("[email protected]<mailto:[email protected]>", >>>>"savaillon".toCharArray()); >>>> >>>>And I'm unable to retrieve the usename and the password. >>>>Request contains following fields : >>>>In headers : >>>>content-lenght : 273 >>>>content-type : application/x-www-form-urlencoded; charset=UTF-8 >>>>host : localhost:8080 >>>>conection : Keep-Alive >>>>user-agent: Apache-HttpClient/4.2.3 (java 1.5) >>>>In params : >>>>update : my update >>>>No attribute. >>>> >>>>I tried to follow in the ARQ library the path of my username and >>>>password, and finally they transited to the applyAuthentication in >>>>HttpOp. >>>> >>>>This method create a CredentialsProvider and set the credentials >>>>username >>>>and >>>> password. But this method has a void return type, and I don't see any >>>>communication point with the rest of the HttpOp code. >>>> >>>>Do I missed something ? >>>> >>>>VAÏSSE-LESTEVEN Arthur. >>>> >>>> >>>>>I was using the 2.9.2 ARQ version. I'll update to 2.10.1. >>>>>Thanks for your quick answer and for your work Rob! >>>>> >>>>>VAÏSSE-LESTEVEN Arthur. >>>>> >>>>> >>>>>>What version of ARQ are you using? >>>>>> >>>>>>I put changes in place which went into the 2.10.1 release which >>>>>>should >>>>>>permit easy HTTP auth on SPARQL updates. Both >>>>>>UpdateExecutionFactory.createRemote() and >>>>>>UpdateExecutionFactory.createRemoteForm() return an instance derived >>>>>>from >>>>>>UpdateProcessRemoteBase which has a setAuthentication() method >>>>>> >>>>>>If you are using a version of ARQ prior to 2.10.0 there is no common >>>>>>base >>>>>>class but both UpdateProcessRemote and UpdateProcessRemoteForm >>>> would still >>>>>>have a setHttpContext() method which allows you to pass in a >>>>>>HttpContext >>>>>>which can be used to pass in authentication settings using the >>>>>>HttpClient >>>>>>APIs. Even with 2.10.1 you can still choose to use this method >>>>>>particularly if you need to pass complex credentials. >>>>>> >>>>>>Rob >>>>>> >>>>>> >>>>>>On 6/18/13 8:10 AM, "Arthur Vaïsse-Lesteven" >>>>>><[email protected]<mailto:[email protected]>> >>>>>>wrote: >>>>>> >>>>>>>Hi, >>>>>>> >>>>>>> >>>>>>>The remote execution of SPARQL queries offer the >>>>>>>setBasicAuthentication >>>>>>>fonctionality(1). I'm using it; and when I tried to use it with >>>>>>>SPARQL >>>>>>>Update it appears that SPARQL Update doesn't handle Authentication. >>>>>>>I would like to know, do it exist any way to do the same thing in >>>>>>>ARQ >>>>>>>? I >>>>>>>writted some code by extending 2 apache classes, but it would be >>>> better >>>>>>>to just use the API. Do you intend to not allow >>>>>>>basicAuthentification >>>>>>>? >>>>>>>It is incompatible with http basic authentication ? There are only >>>>>>>24hours per day and you don't had the time to do it yet ? >>>>>>> >>>>>>>Do this functionality is planed ? >>>>>>> >>>>>>>____________________________________________________________________ >>>>>>>__ >>>>>>>_ >>>>>>>_ >>>>>>> >>>>>>>(1) What i can write : >>>>>>> >>>>>>>[...] >>>>>>> >>>>>>> >>>>>>>QueryEngineHTTP exec = (QueryEngineHTTP) >>>>>>>QueryExecutionFactory.createServiceRequest(endpoint_URL, query); >>>>>>>exec.setBasicAuthentication(user, password); >>>>>>> >>>>>>>exec.exec... >>>>>>> >>>>>>>[...] >>>>>>> >>>>>>>(2)What I want to write : >>>>>>> >>>>>>>[...] >>>>>>>UpdateProcessRemote exec = >>>> (UpdateProcessRemote) >>>>>>>UpdateExecutionFactory.createRemote(update, endpoint_URL); >>>>>>>exec.setBasicAuthentication(user, password); >>>>>>> >>>>>>>exec.excute(); >>>>>>> >>>>>>>[...] >>>>>>> >>>>>>> >>>>>>> >>>>>>>I tried to custom the UpdateProcessRemote class to allow (2). This >>>>>>>currently don't work on my computer, but it seem's to be due to a >>>>>>>maven >>>>>>>version conflict at level of HttpClient. This class must be >>>>>>>compatible >>>>>>>with current version of Jena.( I set my modifications in bold ).( >>>>>>>also >>>>>>>downlodable at : http://arthurvaisse.free.fr/classes/ ) >>>>>>> >>>>>>>Thank you, >>>>>>>VAÏSSE-LESTEVEN Arthur. >>>>>>> >>>>>>> >>>>>>>____________________________________________________________________ >>>>>>>__ >>>>>>>_ >>>>>>>_ >>>>>>> >>>>>>>public class UpdateProcessRemote >>>> implements UpdateProcessor{ >>>>>>> >>>>>>> private String user = null ; >>>>>>> private char[] password = null ; >>>>>>> >>>>>>> private final UpdateRequest request ; >>>>>>> private final String endpoint ; >>>>>>> >>>>>>> public UpdateProcessRemote(UpdateRequest request , String >>>>>>>endpoint >>>>>>>) >>>>>>> { >>>>>>> this.request = request ; >>>>>>> this.endpoint = endpoint ; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> @Override >>>>>>> public void setInitialBinding(QuerySolution binding) >>>>>>> { >>>>>>> throw new ARQException("Initial bindings >>>> for a remote update >>>>>>>execution request not supported") ; >>>>>>> } >>>>>>> >>>>>>> @Override >>>>>>> public GraphStore getGraphStore() >>>>>>> { >>>>>>> return null ; >>>>>>> } >>>>>>> >>>>>>> @Override >>>>>>> public void execute() >>>>>>> { >>>>>>> String reqStr = request.toString() ; >>>>>>> HttpOpCustom.execHttpPost(endpoint, >>>>>>>WebContent.contentTypeSPARQLUpdate, reqStr, user, password); >>>>>>> } >>>>>>> >>>>>>> //comes from QueryEngineHTTP. >>>>>>> public void >>>> setBasicAuthentication(String user, char[] password) >>>>>>> >>>>>>> { >>>>>>> this.user = user ; >>>>>>> this.password = password ; >>>>>>> } >>>>>>>____________________________________________________________________ >>>>>>>__ >>>>>>>_ >>>>>>>_ >>>>>>> >>>>>>>I added this functions to HttpOp to create my custom HttpOp : >>>>>>> >>>>>>> //Just added credentials in parameters >>>>>>> public static void execHttpPost(String url, String contentType, >>>>>>>String content, String user, char[] password) >>>>>>> { >>>>>>> execHttpPost(url, contentType, content, null, null, user, >>>>>>>password) ; >>>>>>> >>>> } >>>>>>> >>>>>>> >>>>>>> //Just added credentials in parameters >>>>>>> public static void execHttpPost(String url, String contentType, >>>>>>>String content, >>>>>>> String acceptType, Map<String, HttpResponseHandler> >>>>>>>handlers, >>>>>>> String user, char[] password) >>>>>>> { >>>>>>> StringEntity e = null ; >>>>>>> try >>>>>>> { >>>>>>> e = new StringEntity(content, "UTF-8") ; >>>>>>> >>>> e.setContentType(contentType) ; >>>>>>> execHttpPost(url, e, acceptType, handlers, user, >>>>>>>password) >>>>>>>; >>>>>>> } catch (UnsupportedEncodingException e1) >>>>>>> { >>>>>>> throw new ARQInternalErrorException("Platform does not >>>>>>>support required UTF-8") ; >>>>>>> } finally { closeEntity(e) ; } >>>>>>> } >>>>>>> >>>>>>> >>>>>>> public static void execHttpPost(String url, HttpEntity >>>>>>>provider, >>>>>>> String acceptType, Map<String, HttpResponseHandler> >>>> handlers, >>>>>>> String user, char[] password) >>>>>>> { >>>>>>> try { >>>>>>> long id = counter.incrementAndGet() ; >>>>>>> String requestURI = determineBaseIRI(url) ; >>>>>>> String baseIRI = determineBaseIRI(requestURI) ; >>>>>>> >>>>>>> HttpPost httppost = new HttpPost(requestURI); >>>>>>> >>>>>>> if ( user != null || password != >>>> null){ >>>>>>> if(user==null || password == null){ >>>>>>> log.warn("Only one of user/password is set") ; >>>>>>> } >>>>>>> //this code come from httpQuery >>>>>>> StringBuffer x = new StringBuffer() ; >>>>>>> byte b[] = >>>>>>>x.append(user).append(":").append(password).toString().getBytes("UTF >>>>>>>-8 >>>>>>>" >>>>>>>) >>>> ; >>>>>>> String y = Base64.encodeBase64String(b) ; >>>>>>> //this single code line is mine >>>>>>> httppost.addHeader("Authorization", "Basic "+y); >>>>>>> } >>>>>>> if ( log.isDebugEnabled() ) >>>>>>> log.debug(format("[%d] %s %s",id >>>>>>>,httppost.getMethod(),httppost.getURI().toString())) ; >>>>>>> >>>>>>> if ( >>>> provider.getContentType() == null ) >>>>>>> log.debug(format("[%d] No content type")) ; >>>>>>> >>>>>>> // Execute >>>>>>> HttpClient httpclient = new DefaultHttpClient(); >>>>>>> httppost.setEntity(provider) ; >>>>>>> HttpResponse response = httpclient.execute(httppost) ; >>>>>>> httpResponse(id, response, baseIRI, handlers) ; >>>>>>> >>>>>>> >>>> httpclient.getConnectionManager().shutdown(); >>>>>>> } catch (IOException ex) >>>>>>> { >>>>>>> ex.printStackTrace(System.err) ; >>>>>>> } >>>>>>> finally { closeEntity(provider) ; } >>>>>>> }
