How Authentication works with MoinMoin
MoinMoin historically has supported only username/password authentication and cookie-based sessions: you log in via the login form, moin sets a cookie and from then on this cookie is used for authenticating you - until you log off and the cookie gets deleted (or until the cookie expires).
In many environments this is often not optimal as access restrictions should be based on other user databases like LDAP (Active Directory). Hence, modular authentication was developed for MoinMoin. You use the auth configuration value to set up a list of authenticators that are processed in exactly that order.
When an external user database is used you do not want to recreate all users in moin. For this case the configuration option user_autocreate was added. If you set it to True a new user profile will be created automatically when a new user has passed authentication (and the authenticator supports auto creation).
Presently the following authenticators are supported:
Authenticator class in moin
by moin via username/password
by PHP session
by moin via external cookie
see contrib/auth_externalcookie/ and HelpOnAuthentication/ExternalCookie
OpenID verification by http://botbouncer.com/
Apache with CGI, modpy or FastCgi
by Apache modules: HTTP Basic, HTTP Digest, SSPI (aka NTLM) or LDAP
by moin via LDAP
by moin via a remote moin wiki
MoinMoin.auth.interwiki - still experimental
Apache+SSL with CGI, modpy or FastCgi
by Apache via SSL client certificate
HTTP Basic (but does not request authentication by header, so this is currently only useful for automated stuff, not for browser use; uses Moin's internal user database but on its own does not allow signing up, hence only useful together with MoinAuth)
HTTP Basic, SSPI (aka NTLM), (?)
These are not strictly authenticators, as they don't authenticate users, but use auth information for other purposes:
will just log login/logout/request, nothing else
mount some smb share using user/password from login, umount on logout
This is the default auth list moin uses (so if you just want that, you don't need to configure it).
1 from MoinMoin.auth import MoinAuth 2 auth = [MoinAuth()]
To activate http authentication you have to add following lines to wikiconfig.py:
1 from MoinMoin.auth.http import HTTPAuth 2 auth = [HTTPAuth()]
For HTTP basic auth used with a web server like Apache, the web server handles authentication before moin gets called. You either enter a valid username and password or your access will be denied by the web server.
Moin's HTTP authenticator will just check if user authentication happened and allow access if it has and a valid user is found for the given username.
Unfortunately, it is a bit more complicated:
- For Twisted servers the authenticator uses the username and password stored in the moin user profile and allows users to change them both.
For NTLM and Negotiate, it splits off everything before the last backslash ("\") (usually it is "Domain\username") and we also use title() to normalize "username" to "Username".
The user_autocreate configuration value should be set to True for this authenticator to allow it to create new user profiles for authenticated users that do not have a profile yet.
See also HelpOnInstalling/ApacheOnWin32withDomainAuthentication for some win32-specific instructions.
SSL client certification authentication
To activate authentication via SSL client certificates you have to add following lines to wikiconfig.py:
1 from MoinMoin.auth.sslclientcert import SSLClientCertAuth 2 auth = [SSLClientCertAuth()]
SSL client certification authentication must be used with a web server like Apache that handles the SSL bits and just presents a few environment variables to Moin.
The SSLClientCertAuth authenticator has a few parameters that you pass to the constructor (example below):
a list of authorities that are accepted, or None to accept all
indicates whether the email in the certificate should be used to find the Moin user
indiciates whether the name in the certificate should be used to find the Moin user
if set to True, the account email cannot be changed and is forced to the one given in the certificate
if set to True, the account name cannot be changed and is forced to the one given in the certificate
For example, to accept only certificates that Apache has verified and that are signed by a certain authority, use:
1 from MoinMoin.auth.sslclientcert import SSLClientCertAuth 2 auth = [SSLClientCertAuth(authorities=['my.authority.tld'])]
You usually want to set user_autocreate = True in the configuration if you use this authenticator. Moin will then automatically create a user profile if the authenticated user does not already have one.
To activate Single-Sign-On integration with PHP applications, use this module. It reads PHP session files and therefore directly integrates with existing PHP authentication systems.
To use this module, use the following lines of code in your configuration:
1 from MoinMoin.auth.php_session import PHPSessionAuth 2 auth = [PHPSessionAuth()]
PHPSessionAuth has the following parameters:
1 PHPSessionAuth(apps=['egw'], s_path="/tmp", s_prefix="sess_")
apps is a list of enabled applications
s_path is the path of the PHP session files
s_prefix is the prefix of the PHP session files
The only supported PHP application is eGroupware 1.2 currently. But it should be fairly easy to add a few lines of code that extract the necessary information from the PHP session, if you do that, please open a feature request with a patch.
OpenID (with BotBouncer)
The OpenID authentication plugin allows users to sign in using their OpenID and connect that OpenID to a new or existing Moin account. To allow users to sign in with OpenID, add the plugin to the auth list, or to require OpenID with http://botbouncer.com/ verification use:
1 from MoinMoin.auth.openidrp import OpenIDAuth 2 from MoinMoin.auth.botbouncer import BotBouncer 3 auth = [OpenIDAuth(), BotBouncer("your-botbouncer-API-key")]
OpenID authentication requires anonymous sessions, set anonymous_session_lifetime to anything bigger than zero. See HelpOnConfiguration for more details on the value. For OpenID, very little time should be sufficient.
Advanced OpenID RP configuration
The OpenID RP code can also be configured for two use cases:
- You can force a specific provider to be used, there are two ways to achieve this:
Simply configure the OpenIDAuth authenticator like this:
auth = OpenIDAuth(forced_service='http://myopenid.com/')
Create an OpenIDServiceEndpoint object and use that for the forced_service parameter:
fs = OpenIDServiceEndpoint() fs.type_uris = OPENID_2_0_TYPE fs.server_url = 'http://localhost:8000/openidserver' fs.claimed_id = 'http://specs.openid.net/auth/2.0/identifier_select' auth = OpenIDAuth(forced_service=fs)
You can specify functions to be called in various steps of the OpenID authentication process to, for example, implement Attribute Exchange. For now, this is not documented here, you'll have to look at the file MoinMoin/auth/openidrp.py.
LDAP based user authentication
The LDAP authenticator of MoinMoin enables single-sign-on (SSO) - assuming you already have a LDAP directory with your users, passwords, email adresses. On Linux this could be some OpenLDAP server, on a Windows server (usually the domain controller) this is called "Active Directory" (short: AD).
It works like this:
- User enters his name and password via moin's login action and clicks on the login button.
- On login, ldap_login.LDAPAuth checks username/password against LDAP.
If username/password is ok for LDAP, it creates or updates a user profile with values from ldap (name, alias, email) and creates a user object in the MoinMoin process, then it hands over to the next authenticator...
- If username/password is not ok for LDAP, it vetoes and aborts the login (no other authenticators checked).
- If the login was successful, moin establishes a session for that user.
LDAP auth installation / configuration
You need to install python-ldap module (and everything it depends on, see its documentation).
You need an LDAP or AD server.
See wiki/config/more_samples/ldap_wikiconfig_snippet.py in your moin dist archive for a snippet you can use in your wiki config.
Please also read the README file in that directory.
LDAP auth Problems?
MoinMoin support does not know your LDAP server setup, so please follow these steps before asking for help:
Configure DEBUG logging for MoinMoin.auth.ldap_login and look into the log output.
- Verify your settings and your user/password by e.g. using ldapsearch to query your LDAP server.
As long as you don't manage talking to your LDAP server with such a tool, you don't need to try with MoinMoin.
- Ask the administrator of your LDAP/AD server for help / for correct settings.
Maybe look into MoinMoin/auth/ldap_login.py, if you can debug or fix your problem there.
Only ask MoinMoin support if you successfully used ldapsearch (or some similar tool) and you double checked your wiki config and it does still not work with moin.
1 import xmlrpclib 2 3 name = "TestUser" 4 password = "secret" 5 wikiurl = "http://localhost:8080/" 6 7 homewiki = xmlrpclib.ServerProxy(wikiurl + "?action=xmlrpc2", allow_none=True) 8 auth_token = homewiki.getAuthToken(name, password) 9 10 mc = xmlrpclib.MultiCall(homewiki) 11 mc.applyAuthToken(auth_token) 12 # you can add more xmlrpc method calls to the multicall here, 13 # they will run authenticated as user <name>. 14 result = mc()
Combining multiple authenticators
For combining e.g. SSL client certificate and username/password authentication, your wikiconfig.py might contain:
1 from MoinMoin.auth import MoinAuth 2 from MoinMoin.auth.sslclientcert import SSLClientCertAuth 3 auth = [SSLClientCertAuth(), MoinAuth()]
In that case, any client certificates that the user provides will be used to log him on, but if they do not provide one they still have the option of logging on with their username/password.
Writing your own authenticator
See the commented config file fragment contrib/auth_externalcookie/ and MoinMoin/auth/*.py in your moin distribution archive for examples of how to do authentication. Also, the docstring in MoinMoin/auth/__init__.py contains an explanation of what can be done and how it is achieved.
- use the regular login form as their user interface for entering name and password
- use the regular logout action for logging out
- prohibit logging out (like SSL client certificate authentication that checks for every request)
- search existing user profiles for a "matching" user (the match needs not be the name, it can also be the email address or something you put into aliasname)
- create a user object and let it remember what attributes were determined by authenticator (and thus should not be offered on user preferences)
- update values in user's profile from externally provided data
- autocreate user profiles