Roger Haase wrote:

> This page may help:
>   http://moinmo.in/HelpOnAuthentication/ExternalCookie
> 
> Roger Haase

Thanks!

Do you know if this code works properly? Comments say that it's outdated...

I have already solved it by adding PHP Session authenticator to the list. 

Anyway, maybe someone will find this authenticator useful.
It uses remote http(s) host with authentication for verifying if it can 
authenticate on that host with supplied username and password.
It can also optionally check if returned webpage matches given string,
and optionally set email for users created.

So in my wikiconfig.py I have following entry (for remote https 
authentication at the University of Waterloo):

    auth = [PHPSessionAuth(),
        RemoteHttpAuth(auth_url="https://ego.uwaterloo.ca/Authen";,
                                required_web_content="OK\n",
                                auto_email_domain="uwaterloo.ca",
                                autocreate=True)]

# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - auth plugin using remote http(s) server with
    authentication.
    Based on a code found here:
    http://www.voidspace.org.uk/python/articles/authentication.shtml
    
    @copyright: 2009 Jakub Schmidtke <shjakub-at-gmail.com>
    @license: GNU GPL, see COPYING for details.
"""

import urllib2
import sys
import re
import base64
from urlparse import urlparse

from MoinMoin import config, user

from MoinMoin.auth import BaseAuth, CancelLogin, ContinueLogin

class RemoteHttpAuth(BaseAuth):
    """ 
        Auth plugin using remote http(s) authentication
    """
    name = 'remote_http'
    login_inputs = ['username', 'password']
    logout_possible = True
        
    def __init__(self,
        auth_url,                    # url used for authentication:
                                     #http(s)://server_with_authentication/some_page
        required_web_content = None, # Content required from URL if properly authenticated.
                                     # Content fetched from URL should be equal to this value\
                                     # (if specified, if not this test is not performed)
	auto_email_domain = None,    # if set, it will be used for registering automatic
	                             # email for new users, in form: usern...@auto_email_domain
	autocreate = False,          # should new users be created?
        ):
        BaseAuth.__init__(self)
        self.auth_url = auth_url
        self.required_web_content = required_web_content
	self.auto_email_domain = auto_email_domain
        self.autocreate = autocreate;

    def login(self, request, user_obj, **kw):
        username = kw.get('username')
        password = kw.get('password')
        _ = request.getText

        if not username or not password:
            return ContinueLogin(user_obj)
    
        req = urllib2.Request(self.auth_url)
        
        try:
            handle = urllib2.urlopen(req)
        except IOError, e:
            # here we *want* to fail
            pass
        else:
            # If we don't fail then the page isn't protected
            return ContinueLogin(user_obj, _("Error Authenticating: URL used for RemoteHttpAuth "
                    " does not require authentication. Please contact administrator."))

        if not hasattr(e, 'code') or e.code != 401:
            # we got an error - but not a 401 error
            return ContinueLogin(user_obj, _("Error Authenticating: URL used for RemoteHttpAuth "
                    "does not require authentication or failed for antoher reason. "
                    "Please contact administrator."))

        authline = e.headers['www-authenticate']
        # this gets the www-authenticate line from the headers
        # which has the authentication scheme and realm in it

        authobj = re.compile(r'''(?:\s*www-authenticate\s*:)?\s*(\w*)\s+realm=['"]([^'"]+)['"]''', re.IGNORECASE)
        # this regular expression is used to extract scheme and realm
        matchobj = authobj.match(authline)

        if not matchobj:
            # if the authline isn't matched by the regular expression
            # then something is wrong
            return ContinueLogin(user_obj, _("Error Authenticating: Authentication header received from URL "
                    "used for RemoteHttpAuth is badly formed. Please contact administrator."))

        scheme = matchobj.group(1)
        realm = matchobj.group(2)
        # here we've extracted the scheme
        # and the realm from the header
        if scheme.lower() != 'basic':
            return ContinueLogin(user_obj, _("Error Authenticating: RemoteHttpAuth requires BASIC authentication "
                    "instead of '" + scheme + "'. Please contact administrator."))

        base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
        authheader =  "Basic %s" % base64string
        req.add_header("Authorization", authheader)
        
        try:
            handle = urllib2.urlopen(req)
        except IOError, e:
            # here we shouldn't fail if the username/password is right
            return ContinueLogin(user_obj, _("Incorrect username or password."))

        thepage = handle.read()

	if self.required_web_content:
	    if thepage != self.required_web_content:
		return ContinueLogin(user_obj, _("Authorization failed: '%s'" %(str(thepage))))
    
        u = user.User(request, name=username, auth_username=username, auth_method=self.name,
		auth_attribs=('name', 'auth_username', 'password'))

	if self.autocreate and self.auto_email_domain and not u.email:
	    u.email = username + "@" + self.auto_email_domain

	u.valid = True

        if u and self.autocreate:
            u.create_or_update(True)

        return ContinueLogin(u)

------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Moin-user mailing list
Moin-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/moin-user

Reply via email to