Adapting Sakai Authentication and Authorization
The SakaiVre project aims to use Shibboleth for authentication of users to Sakai, and provision of attributes upon which Sakai access control decisions can be based. This page contains some notes about how we might be able to achieve this.
Note: This page is somewhat misnamed, since we now learn that it is the Sakai GroupProvider interface that handles requests for role information used for access control.
Contents:
Contents
1. Sakai UserDirectoryProvider
Sakai looks to an implementation of UserDirectoryProvider (file /user/user-api/api/src/java/org/sakaiproject/user/api/UserDirectoryProvider.java) to provide authentication information, and access to some basic information (email, firstname, etc.) for a user (see /user/user-api/api/src/java/org/sakaiproject/user/api/UserEdit.java).
This seems to be a logical place to hook in to a Shibboleth infrastructure.
From [1] (slide 25):
- User Directory Provider
- Very mature - since Sakai 1.0
- User type is controlled by provider - this controls the user template when the user is created
- Can provide fully populated User objects or just answer ID/PW queries
- Consulted at log-in
- Supports special “properties” known to the provider
- Sample providers in release 2.0: JLDAP, OpenLDAP, Kerberos, and IMS Enterprise in a database
Also slide 33:
- Realm Provider (Role)
- Consulted at login
- What are the sites and roles within each site for this user
- If the system is using many different roles throughout, this code must feed the proper site the proper role
- Sakai internal tables are updated as changes from the provider are noticed
User role is similar to, but not the same as a user type. I think type is scoped to a site or system, but role is particular to an administrative domain. Also, type is fixed at login, but roles may change dynamically during a session in response to external administrative changtes. Ultimately, access decisions are based on role membership. Access to role and principal information is provided by an instantiation of the GroupProvider interface (see /authz/authz-api/api/src/java/org/sakaiproject/authz/api/GroupProvider.java).
2. Digging in the code
The javadocs for the UserDirectoryProvider interface can be found at http://source.sakaiproject.org/release/2.1.2/javadoc/org/sakaiproject/service/legacy/user/UserDirectoryProvider.html and interface itself is defined here
- {{{/sakai-src/legacy-service/service/src/java/org/sakaiproject/service/legacy/user/UserDirectoryProvider.java
}}}
Unfortunately, documentation about how to add a new authentication scheme seems to be rather sparse, apart from the javadocs [2], but the source tree contains some sample code and occasional hints:
- {{{/sakai-src/docs/readme_2-0-0.txt (see section 4)
/sakai-src/providers/README.txt /sakai-src/providers/component/src/webapp/WEB-INF/components.xml /sakai-src/providers/component/project.xml /sakai-src/providers/jldap/src/java/edu/amc/sakai/user/JLDAPDirectoryProvider.java /sakai-src/providers/jldap/README_JLDAP.txt }}}
There is a bit more documentation associated with the Kerberos provider:
- {{{/sakai-src/providers/kerberos/docs/INSTALL.txt
/sakai-src/providers/kerberos/src/java/org/sakaiproject/component/kerberos/user/KerberosUserDirectoryProvider.java }}}
Examination of the interface for UserDirectoryProvider seems to indicate that the authentication interface is always used with a supplied user id. But with Shibboleth, the User id is determined in the web request processing path, and provided in the HTTP request headers, so we need to figure a way to get Sakai to use the supplied value rather than prompt for a new username.
Someone else seems to have trod this path: http://tp.its.yale.edu/pipermail/cas/2004-November/000882.html:
- "What we do at U of M for CTools, which uses an Apache based single sign-on called COSIGN, is to enable the COSIGN checking for ONLY the login url. That way when we want a user to be logged in, it goes though the single sign-on system, and if successful, we see the remote user set and we establish a session for the user. All other requests do not go through the single sign-on (and in fact the request remote user is not set), but the user's session has already been established. The path we protect is:
- /tunnel/sakai-chef-tool/authn
- /login
This is pretty much what I was hoping to do (cf. SakaiVre/ShibbolethWebAuthIntegration#Levels) But this doesn't say how to actually establish the user session based on the SSO credentials. There's more: http://tp.its.yale.edu/pipermail/cas/2004-December/000889.html. The key steps seem to be:
- edit sakai.properties:
- {{{top.login = false
container.auth = true }}}
- optionally edit webapps/sakai-chef-tool/vm/sitenav/login.vm, change "Login" text to "Login through CAS", and add a link to login without CAS.
{{{<input type="button" class="button" value="Login through CAS" onclick="parent.location='$login_url'" />
<input type="button" class="button" value="Login without CAS" onclick="parent.location='/login'" /> }}}
But this leaves a remaining question about how similar CAS is to Shibboleth in the way that it supplies credentials. Looking at https://content.cc.vt.edu/confluence/display/DEV/Sakai+Installation+Notes, it appears that container.auth = true or container.login = false is key here. So maybe I just need to check out sakai.properties, following http://cvs.sakaiproject.org/release/2.0.1/SourceInstallGuide.html#Configuration.
Check out /sakai-src/docs/sakai.properties;
- {{{# to let the container handle login or not
# (set to true for single-signon type setups, false for just internal login) container.login = false }}} Not a lot of help there, then. But there is also a document docs/architecture/sakai_properties.doc, but that doesn't really add any useful information.
So how do we get the container login details to the UserDirectoryProvider module?
The page at http://bug.sakaiproject.org/confluence/display/ENTR/CASifying+Sakai suggests that if Tomcat is being fed via Apache and the JK filter module, then the necessary authentication details established by the chosen authentication module in Apache HTTPD (which is how our Shibboleth deployment is set up) are passed automatically to the servlet container and will hence be picked up by Sakai. Does this mean that Sakai will not call the UserDirectoryProvider module, or will it still attempt to obtain attributes that way? I think we'll want to map the user type (e.g. see oucsStatus in SakaiVre/AttributeMappingsTable) to something that can be used across our federation to query or test for role membership.
3. Simple authentication
Based on the message at http://tp.its.yale.edu/pipermail/cas/2004-December/000889.html, and documentation at http://bugs.sakaiproject.org/confluence/display/ENTR/CASifying+Sakai, we tried to create a very simple authentication(-only) scheme for Sakai using Shibboleth. That is, allowing a Shibboleth authentication to be accepted in place of Sakai's default interactive username/password login.
What we did:
The Apache HTTPD, Tomcat and JK connector have already been installed and configured (see TomcatNotes).
Arrange to access Sakai via Apache HTTPD and the JK connector. File /etc/httpd/conf.d/jk.conf was edited to contain:
{{{JkMount /portal ajp13w
JkMount /portal/* ajp13w JkMount /library/* ajp13w JkMount /sakai-login ajp13w JkMount /sakai-login/* ajp13w }}}
- where 'ajp13w' is an AJP/1.3 protocol worker defined in the workers.properties file.
- Test that the Sakai portal can now be accessed using the standard HTTP port (as opposed to the Tomcat port 808 - at this stage, access via port 8080 is also possible.)
Apply Shibboleth access control via the Shibboleth SP configuration file (default /etc/httpd/conf.d/shib.conf, but we use /etc/httpd/conf.d/shib-sp.conf:
{{{<location /sakai-login>
AuthType shibboleth ShibRequireSession On require valid-user
</Location> }}}
Note: some instructions indicate that it is <location /portal/login>... that needs to be protected. While this will force a Shibboleth login, this does not allow Sakai to recognize the remote user information. So use /sakai-login as above, or with Sakai version 2.2 use /sakai-login-tool. (See discussion on sakai-dev mailing list about 13-14 July 20006.)
Confirm that Tomcat authentication is disabled for requests incoming on the JK connector - this allows tomcat to use Authentication details provided by authentication modules in the Apache HTTPD server. File $CATALINA_HOME/conf/server.xml:
{{{<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009"
- enableLookups="false" redirectPort="8443" protocol="AJP/1.3" address="127.0.0.1"
tomcatAuthentication="false" />
}}}
Tell Sakai to use servlet container authentication information. Create file $CATALINA_HOME/sakai/sakai.properties, containing the following:
- {{{# LOGIN/LOGOUT
# to include the user id and password for login on the gateway site top.login=false
# to let the container handle login or not (set to true for single-signon type setups, false for just internal login) # (different documents give container.login or container.auth, so both are included here.) container.login = true container.auth = true }}}
- Login to Sakai as user admin (default password 'admin'), and create a new user corresponding to the Shibboleth login that will be used. If this step is omitted, Sakai will ignore the Shibboleth-authenticated user and force an interactive login (at URI path '/portal/relogin').
3.1. Configure persistent user database
By default, Sakai uses an in-memory hypersonic database for its user listings, which is re-initialized each time Sakai is restarted. To configure a persistent database using Hypersonic, edit $CATALINA_HOME/sakai/sakai.properties thus:
- {{{# two hsqldb storage options: first for in-memory (no persistence between runs),
# second for disk based #url@javax.sql.BaseDataSource=jdbc:hsqldb:. url@javax.sql.BaseDataSource=jdbc:hsqldb:${sakai.home}/db/sakai.db }}}
3.2. Getting the OUCS username into a SAML assertion
To simply release the OUCS primary usert name, edit file /opt/shiiboleth-idp/etc/resolver.ldap.xml, adding an entry of the form:
{{{<SimpleAttributeDefinition id="urn:mace:dir:attribute-def:oucsPrimaryUsername"> <DataConnectorDependency requires="directory"/>
</SimpleAttributeDefinition> }}}
But this isn't enough to get the username recognized as container authentication username. By default, Shibboleth uses attribute eduPersonPrincipalName to identify the user, so use this instead: {{{<SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonPrincipalName"
- smartScope="oucs.ox.ac.uk"
sourceName="oucsPrimaryUsername">
<DataConnectorDependency requires="directory"/>
</SimpleAttributeDefinition> }}}
In https://authdev.it.ohio-state.edu/twiki/bin/view/Shibboleth/IdPAttributeConfig, we see:
Shibboleth comes with two attribute definitions provided in version 1.3: the SimpleAttributeDefinition, which acts as a basic proxy for attributes supplied by data connectors with some name conversion and attribute scoping added, and a CustomAttributeDefinition, which can be used to configure user-created attribute definition plugins.
and under the description of <SimpleAttributeDefinition id="URN">:
sourceName="<string>": Specifies a different source attribute name to be used in calls to the data connector, while the name on the wire will be the specified id. An example use would be to send a local UniversityID attribute as eduPersonPrincipalName.
3.3. Using a Shibboleth attribute to signal container authentication
The example at https://authdev.it.ohio-state.edu/twiki/bin/view/Shibboleth/AttributeAcceptancePolicy contains this:
{{{<AttributeRule Name="urn:mace:dir:attribute-def:eduPersonPrincipalName"
- Scoped="true" Header="REMOTE_USER"
Alias="user">
- Scoped="true" Header="REMOTE_USER"
</AttributeRule> }}}
In our /etc/shibbboleth/AAP.xml config file, we have placed the following definition:
{{{<AttributeRule Name="urn:mace:dir:attribute-def:oucsPrimaryUsername"
- Header="REMOTE_USER"
Alias="user">
<AnySite>
<AnyValue/>
</AnySite>
- Header="REMOTE_USER"
</AttributeRule> }}}
(Note that we are not using attribute scoping here, which may be a security hole.)
To test this, we Shibboleth-protected the standard Tomcat JSP example pages by adding the following to /etc/httpd/conf.d/shib-sp.conf:
{{{<Location /jsp-examples>
AuthType shibboleth ShibRequireSession On require valid-user
</Location> }}} and then browse to http://sakai-vre-demo.oucs.ox.ac.uk/jsp-examples/snp/snoop.jsp, which displays a page of request information, including the requesting username, generated by this JSP: <%= request.getRemoteUser() %>.
3.4. Linking to servlet authentication
In order to get Shib-EP-Principalname passed to Tomcat, uncomment the following in AAP.xml (and edit the "Header=" attribute if necessary):
{{{<AttributeRule Name="urn:mace:dir:attribute-def:eduPersonPrincipalName" Scoped="true"
Header="Shib-EP-EduPersonPrincipalName" Alias="user">
<AnySite>
<Value Type="regexp">[@]+$</Value>
</AnySite>
</AttributeRule> }}}
The refers to application context parameters or servlet init parameters that may be defined in the application's web.xml configuration file. This example comes from the SPIE test servlet configuration:
<context-param> <!-- use this attribute as username when logging in --> <param-name>attributeAsUsername</param-name> <param-value>Shib-EP-PrincipalName</param-value> <!-- Recommended attributes are Shib-EP-PrincipalName, Shib-EP-TargetedId, ... that uniquely identify a user --> </context-param> <context-param> <!-- the value(s) of this shib-attribute will be used as JAAS roles --> <param-name>attributeAsRoles</param-name> <param-value>Shib-EP-Entitlement</param-value> </context-param>
Here, parameter 'attributeAsUsername' indicates Shibboleth attributes that are mapped to JAAS principals, and 'attributeAsRoles' indicates an attribute that conveys roles that have been assigned to the authenticated user.
4. Using Shibboleth Attributes for access control
Prompted by some questions about how we might use the SPIE JAAS module to pass Shibboleth attributes into Sakai, there has been some lively discussion on the sakai-dev mailing list, and many details have become clearer. In particular, it seems that the Sakai authorization structure is a poor fit with Shibboleth attribute delivery. Alistair Young has encountered similar issues with his Guanxi development, and is taking the approach of constructing a "pod" of data from Shibboleth assertions, suitable for responding to Sakai authorization queries.
The discussion of Shibboleth integration with Sakai on the sakai-dev mailing list occurs about the end of July 2006 and start of August 2006. Key messages have been copied to our internal mailing list and can be reviewed here:
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:134:200607:gddpkpmonkgpgmkebbab - initial query
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:134:gddpkpmonkgpgmkebbab
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:136:gddpkpmonkgpgmkebbab
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:137:lifpfoeehmkehfaikenm
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:138:lifpfoeehmkehfaikenm
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:139:lifpfoeehmkehfaikenm
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:140:lifpfoeehmkehfaikenm
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:141:lifpfoeehmkehfaikenm
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:142:lifpfoeehmkehfaikenm
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:143:lifpfoeehmkehfaikenm
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:144:gddpkpmonkgpgmkebbab
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:145:oidbaffbhnociiomkffb
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:146:djgigamlijbdbgklbmac
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:147:oidbaffbhnociiomkffb
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:148:oidbaffbhnociiomkffb
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:149:oidbaffbhnociiomkffb
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:150:oidbaffbhnociiomkffb
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:151:oidbaffbhnociiomkffb
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:152:oidbaffbhnociiomkffb
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:153:oidbaffbhnociiomkffb
There are also some comments from Steven Carmody of the Internet2 Shibboleth project, and my response:
This discussion has clarified the scope for interaction between Sakai authentication, Sakai authorization and Shibboleth. Unfortunately, it seems that it is not a simple matter to write Sakai providers that simply answer authentication and access control queries on the basis of available Shibboleth attributes, which is what we were looking for. The reason is that Sakai does not provide access to the incoming request context where the Shibboleth attributes are provided to an application. It seems that Sakai, being primarily responsible for handling incoming HTTP requests, assumes that it has extracted all the useful information, and does not allow that provider components might also need access to the request context.
5. References
https://authdev.it.ohio-state.edu/twiki/bin/view/Shibboleth/AttributeNaming - Shibboleth attribute naming
https://authdev.it.ohio-state.edu/twiki/bin/view/Shibboleth/IdPAttributeConfig - Shibboleth attribute release/mapping
https://authdev.it.ohio-state.edu/twiki/bin/view/Shibboleth/AttributeAcceptancePolicy - Shibboleth attribute acceptance policy
6. Other links
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:93:figemojgeookkeabmhcd - CARET project message about CAS
http://bug.sakaiproject.org/confluence/download/attachments/9689/Remote+Sakai+AuthZ.ppt - more from CARET about Sakai authorization
http://saffron.caret.cam.ac.uk/ - CARET source repository access
http://maillist.ox.ac.uk/ezmlm-cgi?3855:mss:94:figemojgeookkeabmhcd - more notes about CAS and Sakai
http://mediaworks.ucdavis.edu:8080/confluence/pages/viewpage.action?pageId=1071 - description of Sakai's use of container authentication
http://bugs.sakaiproject.org/confluence/display/ENTR/CASifying+Sakai - Sakai and container-based authentication
http://bug.sakaiproject.org/confluence/display/FAQ/2.2.8+How+to+CASify+Sakai - ditto
http://www.obs-hp.fr/www/www-faq/cginame.htm - HTTP headers used with remote authentication (as documented for CGI)
https://source.sakaiproject.org/contrib/integration/providers/SKrbLDAP/ - Stanford have done some work with Sakai using Kerberos and LDAP, which might be sort-or relevant. This link is "Casey's SKrbLDAP provider for 2.0". Some of his design was brought back into the main provider at some point (mostly config-type stuff).
-- GrahamKlyne 2006-06-27 12:10:41