Implementing a custom Python authentication handler
Question: The answer to a [previous
question](http://stackoverflow.com/questions/1080179/handling-authentication-
and-proxy-servers-with-httplib2) showed that Nexus implement a [custom
authentication helper](http://svn.sonatype.org/nexus/tags/nexus-1.3.4/nexus-
clients/nexus-rest-client-
java/src/main/java/org/sonatype/nexus/client/rest/HttpNxBasicHelper.java)
called "NxBASIC".

How do I begin to implement a handler in python?

* * *

Update:

Implementing the handler per Alex's suggestion looks to be the right approach,
but fails trying to extract the scheme and realm from the authreq. The
returned value for authreq is:

    
    
    str: NxBASIC realm="Sonatype Nexus Repository Manager API""
    

AbstractBasicAuthHandler.rx.search(authreq) is only returning a single tuple:

    
    
    tuple: ('NxBASIC', '"', 'Sonatype Nexus Repository Manager API')
    

so scheme,realm = mo.groups() fails. From my limited regex knowledge it looks
like the standard regex from AbstractBasicAuthHandler should match scheme and
realm, but it seems not to.

The regex is:

    
    
    rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+'
                    'realm=(["\'])(.*?)\\2', re.I)
    

* * *

Update 2: From inspection of AbstractBasicAuthHandler, the default processing
is to do:

    
    
    scheme, quote, realm = mo.groups()
    

Changing to this works. I now just need to set the password against the
correct realm. Thanks Alex!


Answer: If, as described, name and description are the only differences between this
"NxBasic" and good old "Basic", then you could essentially copy-paste-edit
some code from urllib2.py (which unfortunately doesn't expose the scheme name
as easily overridable in itself), as follows (see
[urllib2.py](http://svn.python.org/view/python/trunk/Lib/urllib2.py?revision=72880&view=markup)'s
online sources):

    
    
    import urllib2
    
    class HTTPNxBasicAuthHandler(urllib2.HTTPBasicAuthHandler):
    
        def http_error_auth_reqed(self, authreq, host, req, headers):
            # host may be an authority (without userinfo) or a URL with an
            # authority
            # XXX could be multiple headers
            authreq = headers.get(authreq, None)
            if authreq:
                mo = AbstractBasicAuthHandler.rx.search(authreq)
                if mo:
                    scheme, realm = mo.groups()
                    if scheme.lower() == 'nxbasic':
                        return self.retry_http_basic_auth(host, req, realm)
    
        def retry_http_basic_auth(self, host, req, realm):
            user, pw = self.passwd.find_user_password(realm, host)
            if pw is not None:
                raw = "%s:%s" % (user, pw)
                auth = 'NxBasic %s' % base64.b64encode(raw).strip()
                if req.headers.get(self.auth_header, None) == auth:
                    return None
                req.add_header(self.auth_header, auth)
                return self.parent.open(req)
            else:
                return None
    

As you can see by inspection, I've just changed two strings from "Basic" to
"NxBasic" (and the lowercase equivalents) from what's in urrlib2.py (in the
abstract basic auth handler superclass of the http basic auth handler class).

Try using this version -- and if it's still not working, at least having it be
your code can help you add print/logging statements, breakpoints, etc, to
better understand what's breaking and how. Best of luck! (Sorry I can't help
further but I don't have any Nexus around to experiment with).

