[Zope-dev] XMLRPC and Basic Auth problems

Tim Hoffman timhoffman@cams.wa.gov.au
15 Aug 2002 11:59:43 +0800


Hi Casey

I am using Basic Auth with xmlrpc lib now, and yes it does work with
Python2.1 but that's not my point.

The XML-RPC spec doesn't talk about authentication,  and so yes what you
say is correct. However Adams position is that the spec says it is
implemented on top of http and the http spec says that an error 
401 needs to be sent if authentication is invalid etc.. So Adam makes
the claim that Zope is not compliant with the http protocol when XML-RPC
is used on top of it. 

And I am inclined to agree.

Regards

Tim

On Thu, 2002-08-15 at 11:47, Casey Duncan wrote:
> Python's xmlrpclib doesn't support any authentication. It is easily subclassed 
> to include it. I have successfully used it to connect with Zope and I do not 
> have any reason to believe that Zope is broken with regard to authentication. 
> 
> However I do think that Python's xmlrpclib should include basic auth. Perhaps 
> I will make an effort to put this in, since it is so easy.
> 
> This how-to provides the code for extending xmlrpclib:
> 
> http://www.zope.org/Members/Amos/XML-RPC
> 
> It doesn't quite work for Python 2.1+, but I have attached a working version I 
> use.
> 
> hth,
> 
> Casey 
> 
> On Wednesday 14 August 2002 10:51 pm, Tim Hoffman wrote:
> > I have had further from Adam Megacz <adam@megacz.com> the author of XWT
> > on this issue.
> > 
> > I believe I should raise a collector issue on this, however do 
> > people believe this is a correct assessment of the situation.
> > 
> > 
> > ======================================================================
> > Tim Hoffman <timhoffman@cams.wa.gov.au> writes:
> > > The xmlrpc spec doesn't say anything about authentication.
> > > ...
> > > I suppose this whole area is pretty vague.
> > 
> > Actually, it references the HTTP spec, which is quite clear about
> > requiring a 401.
> > 
> >   http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
> > 
> > Without the 401, you don't know the authentication realm,
> > authentication type, or digest nonce -- three things you need to know
> > in order to authenticate (although the last one is only needed for
> > Digest auth, not Basic Auth).
> > 
> > Unfortunately, it seems that a lot of XML-RPC libraries are broken in
> > this manner. I'm working with the Apache people right now on fixing
> > the Java libraries -- could you please work with the Python people to
> > get this fixed?
> > 
> > I think this is a result of the fact that HTTP Auth isn't used very
> > often in XML-RPC, although it should be. I'm working on an RFC for
> > XML-RPC, and I will certainly include some wording which underscores
> > the importance of the 401 response.
> > 
> >     http://www.xwt.org/xmc/draft-megacz-xmc-05.txt
> > 
> >   - a
> > 
> > -- 
> > Sick of HTML user interfaces?
> > www.xwt.org
> > =========================================================================
> > 
> > 
> > 
> > On Thu, 2002-08-15 at 10:47, Tim Hoffman wrote:
> > > Hi
> > > 
> > > I am working on a project that uses XWT (xwt.org) as a frontend to Zope.
> > > 
> > > XWT uses XMLRPC to communicate with a backend (in this case Zope).
> > > 
> > > XWT expects an Error 401 is authentication is required on an XMLRPC
> > > call, so that it can negotiate the correct auth method 
> > > 
> > > The author of XWT sent the following email to me
> > > 
> > > >Tim, I've got a piece of the answer -- your server needs to return an
> > > >HTTP 401 (Unauthorized) if no username/password is provided. This
> > > >response includes the challenge that XWT needs in order to build an
> > > >authentication request (realm, digest nonce challenge, etc).
> > > 
> > > However what Zope is doing is sending back a <fault> in the 
> > > XMLRPC <methodResponse> packet. 
> > > 
> > > So it appears to me that Zope doesn't send a http response 401 for 
> > > XMLRPC (over http), but will send a 401 back to the browser.
> > > 
> > > XMLRPC doesn't say anything about authentication, so I suppose either
> > > method is acceptable. However because XMLRPC is implemented 
> > > on top of http, I would have thought a http approach (ie error 401)
> > > would be used.
> > > 
> > > It appears that this behaviour is fundamental to Zope and is not an
> > > artifact of cookie auth in CMF etc..
> > > 
> > > Is this really correct behaviour ?
> > > 
> > > Regards
> > > 
> > > Tim Hoffman
> > > 
> > > 
> > >  
> > > 
> > > 
> > > _______________________________________________
> > > Zope-Dev maillist  -  Zope-Dev@zope.org
> > > http://lists.zope.org/mailman/listinfo/zope-dev
> > > **  No cross posts or HTML encoding!  **
> > > (Related lists - 
> > >  http://lists.zope.org/mailman/listinfo/zope-announce
> > >  http://lists.zope.org/mailman/listinfo/zope )
> > 
> > 
> > 
> > _______________________________________________
> > Zope-Dev maillist  -  Zope-Dev@zope.org
> > http://lists.zope.org/mailman/listinfo/zope-dev
> > **  No cross posts or HTML encoding!  **
> > (Related lists - 
> >  http://lists.zope.org/mailman/listinfo/zope-announce
> >  http://lists.zope.org/mailman/listinfo/zope )
> > 
> 
> ----
> 

> import string, xmlrpclib, httplib
> from base64 import encodestring
> 
> class BasicAuthTransport(xmlrpclib.Transport):
>     verbose = 0
>     
>     def __init__(self, username=None, password=None):
>         self.username=username
>         self.password=password
> 
>     def request(self, host, handler, request_body, verbose=0):
>         # issue XML-RPC request
> 
>         h = httplib.HTTP(host)
>         h.putrequest("POST", handler)
> 
>         # required by HTTP/1.1
>         h.putheader("Host", host)
> 
>         # required by XML-RPC
>         h.putheader("User-Agent", self.user_agent)
>         h.putheader("Content-Type", "text/xml")
>         h.putheader("Content-Length", str(len(request_body)))
> 
>         # basic auth
>         if self.username is not None and self.password is not None:
>             h.putheader("AUTHORIZATION", "Basic %s" % string.replace(
>                     encodestring("%s:%s" % (self.username, self.password)),
>                     "\012", ""))
>         h.endheaders()
> 
>         if request_body:
>             h.send(request_body)
> 
>         errcode, errmsg, headers = h.getreply()
> 
>         if errcode != 200:
>             raise xmlrpclib.ProtocolError(
>                 host + handler,
>                 errcode, errmsg,
>                 headers
>                 )
> 
>         return self.parse_response(h.getfile()) 
> 
>