Comments inline below ...
Dave wrote:
We gained some SSO options back in the 3.0 timeframe, but we never got
any documentation (please correct me if I am wrong) about how to setup
Roller to take advantage of those options.
By using those SSO options and tweaking the LDAP configuration in
Acegi security.xml, it is possible to get Roller working with LDAP.
With this setup, when a new user registers for Roller we are able to
pull her user information from LDAP and setup a new Roller account for
her. We authentication against LDAP (where passwords are stored) and
keep user info info Roller.
With our current setup, I believe here's how things should work:
1) Enable SSO option
Define a roller-custom.properties file, override the users.sso.enabled
option like so:
users.sso.enabled=true
2) Uncomment the LDAP section in Acegi security.xml
Uncomment the section that begins with:
<!-- Sample LDAP/RollerDB hybrid security configuration
3) Protect the user registration page via Acegi security.xml
In the XML for the filterInvocationInterceptor bean, add the user
registration page to the list of URL patterns in the
objectDefinitionSource as shown below. The new line is the one that
reads " /roller-ui/user.do*=register".
What does this do? It requires the user to have the role "register" in
order to view the user registration page. Therefore he user is shown
the login page and expected to enter their LDAP username and password
-- but we don't tell them that so it's pretty confusing. Once the
login, we know their user info so we are able to pre-populate the user
registration form with information from LDAP.
This part sounds wacky to me. The idea that you are already logged in
but you have to register just seems wrong to me. I think that most of
the time when you have many systems sharing a common authentication/sso
service but want local copies of profile data then that should be done
behind the scenes. I think that in Roller's case the sso account data
can automatically be used to create/update a Roller account.
If you look at the data we keep for user profiles then I think it makes
sense that all the data can be automatically synced from the sso session
data ... username, password, fullname, email, locale, timezone.
The main gotcha that I currently see is that Roller publicizes the
account username for some things, but in various cases that is not
desirable. So IMO the way that Roller should be working, and which
solves this problem, is if we add a new "screen name" field to the user
profile and use that as what gets displayed on the site. This way the
username stays hidden and only used for login and screen name can be
whatever the user wants to be known as publicly. We would allow users
to change their screen name whenever they like, which is something that
I know some people have asked for in the past.
So instead of having to force registration for users and deal with that
extra "register" role, we would simply use the provisioning code that
already exists and autosync all profile data when the user first logs in
or is transferred in. Then after the sync has happened the user can be
put on the profile edit page if we need them to choose options for
Roller specific fields.
<bean id="filterInvocationInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="objectDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/roller-ui/login-redirect.jsp=admin,editor
/roller-ui/yourProfile**=admin,editor
/roller-ui/createWebsite**=admin,editor
/roller-ui/yourWebsites**=admin,editor
/roller-ui/authoring/**=admin,editor
/roller-ui/admin/**=admin
/roller-ui/user.do*=register
/rewrite-status*=admin
</value>
</property>
</bean>
4) Enable LDAP authentication provider via security.xml
In the XML for the authenticationManager bean, comment out the DAO
provider and add in the LDAP provider, as shown below:
<bean id="authenticationManager"
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<!-- <ref local="daoAuthenticationProvider"/> -->
<ref local="ldapAuthProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<!-- rememberMeAuthenticationProvider added
programmatically -->
</list>
</property>
</bean>
But that's not all I had to do. I also had to do this:
5) Add LDAP username and password to Acegi security.xml
I've got my LDAP server (OpenDS - https://opends.dev.java.net/ ) setup
to require authentication. So I had to add two new properties to the
initialDirContextFactory bean, as shown below:
<bean id="initialDirContextFactory"
class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">
<constructor-arg value="ldap://localhost:1389/dc=example,dc=com"/>
<property name="managerDn">
<value>cn=Directory Manager</value>
</property>
<property name="managerPassword">
<value>password</value>
</property>
</bean>
6) Change LDAP user search to use uid instead of email in Acegi
security.xml
In the ldapUserSearch bean, I changed mail={0} to uid={0}. Not sure,
but maybe uid is a better default than mail for most users.
<bean id="ldapUserSearch"
class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0">
<value></value>
</constructor-arg>
<constructor-arg index="1">
<value>uid={0}</value>
</constructor-arg>
<constructor-arg index="2">
<ref local="initialDirContextFactory" />
</constructor-arg>
<property name="searchSubtree">
<value>true</value>
</property>
</bean>
7) Java code change in
Added "request.getSession().invalidate();" after line 186 in
NewUserAction, as shown below. Without this change, the user will
remain logged in, but with only the role "register". The user will
have to close his browser and restart before being able to login with
their new account.
} else {
// User registered, so go to welcome page
request.setAttribute("contextURL",
RollerRuntimeConfig.getAbsoluteContextURL());
request.getSession().invalidate();
return mapping.findForward("welcome.page");
}
This one also seems wacky to me. I don't see why you need to remove the
users session in order to fix their login state. And why would the user
need to login again anyways, I thought their session was transferred?
To solve those problems above, I'd like to change security.xml to
include a comments explaining what needs to be done. I'd like to make
that code change in #7 and I'd like to write up a nice friendly wiki
page explaining how to configure Roller and LDAP.
I definitely agree with adding comments in the security.xml on what
needs to be done, and I agree that we should have a wiki page describing
the process. I'm not really onboard with #3 and #7 though.
-- Allen
Any comments or suggestions?
- Dave