OpenID is an open, decentralized, free framework for user-centric digital identity. Users represent themselves using URIs. For more information see the http://www.openid.net. As of CAS 3.1, CAS supports the "dumb" mode of the OpenID protocol. Dumb mode acts in a similar fashion to the existing CAS protocol.
Enabling OpenID Support in the Build
To enable OpenID in your build, edit the pom.xml in the cas-server-webapp module. Add the following entry:
<dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-support-openid</artifactId> <version>${project.version}</version> </dependency>
Giving your users URIs
Configuring your users to have URIs.
You'll need to set up a local mechanism for generating URIs for your users based on their username (i.e. http://openid.rutgers.edu/battags).
The endpoint pages look something like this:
<html> <head> <link rel="openid.server" href="https://localhost/cas/login" /> </head> </html>
Enabling OpenID in CAS
Note: We're assuming you are using the Default AuthenticationManager.
Modifying the deployerConfigContext.xml
Open your deployerConfigContext.xml and add the following entries:
Add a new AuthenticationHandler to your AuthenticationManager
<bean class="org.jasig.cas.support.openid.authentication.handler.support.OpenIdCredentialsAuthenticationHandler" p:ticketRegistry-ref="ticketRegistry" />
Add a new CredentialsToPrincipalResolver to your AuthenticationManager
<bean class="org.jasig.cas.support.openid.authentication.principal.OpenIdCredentialsToPrincipalResolver" />
Modifying the cas-servlet.xml
Add the Url Mapping Handler
Add the following entry to your cas-servlet.xml (it can go anywhere):
<bean id="handlerMappingA" class="org.jasig.cas.support.openid.web.support.OpenIdPostUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/login">openIdValidateController</prop> </props> </property> </bean>
This will direct validation requests to the correct controller.
OpenId Validation Controller
Add the following to enable validation of an OpenID request:
<bean id="openIdValidateController" class="org.jasig.cas.web.ServiceValidateController" p:validationSpecificationClass="org.jasig.cas.validation.Cas20WithoutProxyingValidationSpecification" p:centralAuthenticationService-ref="centralAuthenticationService" p:proxyHandler-ref="proxy20Handler" p:argumentExtractor-ref="openIdArgumentExtractor" p:successView="casOpenIdServiceSuccessView" p:failureView="casOpenIdServiceFailureView" />
ArgumentExtractor
Next, we need to add the ArgumentExtractor that can actually detect the OpenID request:
<bean id="openIdArgumentExtractor" class="org.jasig.cas.support.openid.web.support.OpenIdArgumentExtractor" />
Then, locate the <util:list> entry in the cas-servlet.xml and add a:
<ref bean="openIdArgumentExtractor" />
It should look something like this (it will vary depending on what is enabled):
<util:list id="argumentExtractors"> <ref bean="casArgumentExtractor" /> <ref bean="samlArgumentExtractor" /> <ref bean="openIdArgumentExtractor" /> </util:list>
Add the Action for the Web Flow
Finally, in the cas-servlet.xml you'll need to add the action that we will reference in the login flow xml file:
<bean id="openIdSingleSignOnAction" class="org.jasig.cas.support.openid.web.flow.OpenIdSingleSignOnAction" p:centralAuthenticationService-ref="centralAuthenticationService" />
Be Careful
The OpenIdSingleSignOnAction has an additional parameter not configured here. Its the "extractor" property which accepts a "org.jasig.cas.support.openid.web.support.OpenIdUserNameExtractor". The default one merely accepts the value after the last "/". A more robust implementation should check the entire URL. Note, that means the default one SHOULD NOT be used in production.
login-webflow.xml
Add the following decision and action states to your login-webflow.xml
<decision-state id="selectFirstAction"> <if test="${externalContext.requestParameterMap['openid.mode'] != '' && externalContext.requestParameterMap['openid.mode'] != null}" then="openIdSingleSignOnAction" else="ticketGrantingTicketExistsCheck" /> </decision-state> <action-state id="openIdSingleSignOnAction"> <action bean="openIdSingleSignOnAction" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="viewLoginForm" /> <transition on="warn" to="warn" /> </action-state>
You'll want to modify your InitialFlowAction's "success" event to go to "selectFirstAction". For example:
<action-state id="initialFlowSetup"> <action bean="initialFlowSetupAction" /> <transition on="success" to="selectFirstAction" /> </action-state>
Modify the login view
Instead of the normal NetId login field, any CAS instance that accepts OpenID credentials needs to be able to not accept a Username (as its provided by the OpenID protocol). This can be accomplished with the following snippit of code on the login JSP page:
<c:if test="${not empty sessionScope.openIdLocalId}"> <strong>${sessionScope.openIdLocalId}</strong> <input type="hidden" id="username" name="username" value="${sessionScope.openIdLocalId}" /> </c:if> <c:if test="${empty sessionScope.openIdLocalId}"> <input class="required" id="username" name="username" size="32" tabindex="1" accesskey="<spring:message code="screen.welcome.label.netid.accesskey" />" /> </c:if>