Wiki Markup |
---|
The CAS Server is a Spring Web Application, but it is designed according to standard layers or functional components that can be plugged into a standard J2EE diagram. There are three main components, each of which can be subdivided into subcomponents. |
...
* The front end is a "Presentation Layer" that handles arriving HTTP requests. In addition to presenting and processing the Login form (containing userid and password), this layer also handles non-interactive forms of login (X.509 Certificates), and the Service Ticket validation and Proxy ticket calls. |
...
* The Business Layer (where J2EE would have EJBs) validates the login (by verifying the userid/password against a backend system such as Kerberos or LDAP), and it creates Tickets including the Login TGT and Service Tickets. |
...
* Tickets are stored in a Ticket Cache. Normally this is just an in-memory collection, although it can be replicated (for clustered failover) or stored in a shared database. Since Tickets can be persisted (even though they frequently aren't) they become Entities in a logical Persistence Layer |
...
Presentation Layer
CAS 3 uses two different Spring APIs to configure and code the Presentation Layer.
...
. h2. Presentation Layer CAS 3 uses two different Spring APIs to configure and code the Presentation Layer. The calls to validate Service Tickets and issue Proxy Tickets are processed by *Spring MVC* configured in the WEB-INF/cas-servlet.xml file.Spring "Action" Beans are configured that expose a method that receives the Request and Response object of an incoming HTTP operation. |
...
{code |
} <bean id="serviceValidateController" class="org.jasig.cas.web.ServiceValidateController" p:validationSpecificationClass="org.jasig.cas.validation.Cas20WithoutProxyingValidationSpecification" p:centralAuthenticationService-ref="centralAuthenticationService" p:proxyHandler-ref="proxy20Handler" p:argumentExtractor-ref="casArgumentExtractor" /> {code} Action Beans are essentially Servlets, only with a Spring flavor. Parameters from the request are "bound" (used to set the properties of a bean). The Action Bean is inside the ApplicationContext, so it gets dependency injection. It returns an object (ModelAndView) that identifies the response (typically a JSP page although it can be a View Bean) and provides a Map of data that the JSP EL can use to populate variable fields in the response page. |
...
Each Action Bean is called when the end of a request URL contains a string mapped to the Bean (again in cas-servlet.xml): |
...
{code |
} <prop key="/serviceValidate"> serviceValidateController </prop> {code} The "/login" function is mapped to an entirely separate API called Spring WebFlow. WebFlow is a common computer design pattern called a "State Machine" coded as a sequence of XML elements in the WEB-INF/login-webflow.xml file. In some sense, a WebFlow demonstrates how to replace a dozen lines of Java with a hundred lines of considerably more complex XML (but at least you are not coding). |
...
Each state is represented by an XML element that either performs a simple EL test or else calls a Bean method. The result of the test or return value of the method is "success" or "error" and generates a transition (a GOTO) to another state. |
...
{code |
} <action-state id="startAuthenticate"> <action bean="x509Check" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="viewLoginForm" /> </action-state> |
When the login flow gets to this state, it calls a method of the x509Check Bean (which determines if the Request has a valid X.509 Certificate that can be used to login the user). A return of "success" means the user has logged on and proceeds to a state/bean that generates the Ticket Granting Cookie in the response object. An "error" means that there is no certificate, so the normal interactive Login form is displayed.
The flow continues until there is a transition to an "end-state" which either displays a JSP page or else redirects the Browser to another page.
Ideally, the Presentation Layer would be the only component that deals with the Servlet API and its Request, Response, and Session objects. That is certainly possible for userid/password, but certain credentials may be inherently tied to the underlying socket and communications layers.
Business Logic
...
{code} When the login flow gets to this state, it calls a method of the x509Check Bean (which determines if the Request has a valid X.509 Certificate that can be used to login the user). A return of "success" means the user has logged on and proceeds to a state/bean that generates the Ticket Granting Cookie in the response object. An "error" means that there is no certificate, so the normal interactive Login form is displayed. The flow continues until there is a transition to an "end-state" which either displays a JSP page or else redirects the Browser to another page. Ideally, the Presentation Layer would be the only component that deals with the Servlet API and its Request, Response, and Session objects. That is certainly possible for userid/password, but certain credentials may be inherently tied to the underlying socket and communications layers. h2. Business Logic The Business Logic layer of CAS represents a set of services configured by the WEB-INF/deployerConfigContext.xml file. In a normal J2EE |
...
design, these would be the EJBs. |
...
There is only one service interface exposed by Business Logic. It is the CentralAuthenticationService interface that exposes methods to create a TicketGrantingTicket (by logging on a user if the credentials presented are valid), create and validate ServiceTickets, and log the user off. All the other components provide support services to this interface. |
...
The most important support service, and the most important configuration option for CAS, is the Bean implementing the AuthenticationManager interface configured to id "authenticationManager" in deployerConfigContext.xml. This Bean has two properties that each receive a list of configured Beans: the authenticationHandlers and credentialsToPrincipalResolvers properties. An AuthenticationHandler Bean examines the credentials and determines if they are valid. For example, a userid and password can be presented to a back-end service (Kerberos 5, LDAP, JDBC) for validation, or an X.509 Certificate can be found valid if it was issued by a trusted Certificate Authority. A CredentialsToPrincipalResolver extracts the Principal (user) from the Credentials. For a userid/password, the Principal is just the userid. However, an X.509 certificate has a Distinguished Name and various SubjectAltNames from which a Principal may be determined. There is also the question of whether the Principal name should be qualified or not. At Yale, the Netid "gilbert" may also be identified as "yale\gilbert" (AD), "gilbert@YU.YALE.EDU" (Kerberos realm), "Howard.Gilbert@yale.edu" (EMail address and AD Universal Principal Name). Fully qualified principal names become more important when independent organizations join in some sort of Identity Federation. Different AuthenticationHandlers may validate different types of credentials, or the same credentials may be validated in different backend systems depending on the association of the user (alumni, applicant, ...). h3. JAAS (Kerberos) Password Validation {code} <bean class="org.jasig.cas.authentication.handler.support.JaasAuthenticationHandler" p:realm="K5auth" /> {code} The JaasAuthenticationHandler uses the JAAS Java API to authenticate a userid and password against an external Kerberos 5 or LDAP system. The realm parameters (set to "K5auth") is just the name of a bundle of configuration parameters in the login configuration file. In normal Java, a login configuration file is specified by the "login.config.url.1" property in the {jre}/lib/security/java.security property file. An application specific configuration file can be provided by the Java code that calls JAAS. Each JAAS login configuration file contains named bundles of configuration parameters designating the name of a class that provides the JAAS login service and a list of parameters needed by that class to connect to the Kerberos KDC, the LDAP server, etc. When more than one login configuration file is specified, they are concatenated. An exception is thrown if the same named configuration bundle is found more than once, say in the JRE configuration file and the local application configuration file. JAAS uses the credentials (typically the userid and password) to log the user on to the backend system and generates some standard Java objects (Subject and Principal). If the backend system is a Kerberos 5 KDC, then the generated Principal object can contain a key and a Kerberos TGT. However, the JaasAutheticationHandler does not use artifacts generated by the login. It simply uses JAAS to autheticate the userid/password combination and then logs the user off from the backend system before returning to the AuthenticationManager. h3. LDAP Password Validation {code} <bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler"> <property name="filter" value="sAMAccountName=%u" /> <property name="searchBase" value="dc=yu,dc=yale,dc=edu" /> <property name="contextSource" ref="ldapContextSource" /> <property name="ignorePartialResultException" value="yes" /> <!-- fix because of how AD returns results --> </bean> {code} An LDAP AutheticationHandler is one of the distributed optional modules of the CAS 3 distribution. It uses Spring LDAP to authenticate the userid and password. In this example, the bean is configured for Active Directory and uses a separate LdapContextSource bean not shown. JAAS can authenticate a userid/password by logging the user on and then off of an external LDAP source. However, the BindLdapAuthenticationHandler shown here is more efficient because it maintains a pool of existing LDAP connections to AD that it reuses to validate passwords rather than setting up and tearing down a connection for every user login. h3. X.509 Certificate Validation {code} <bean class="org.jasig.cas.adaptors.x509.authentication.handler.support.X509CredentialsAuthenticationHandler" p:trustedIssuerDnPattern="CN=Yale University ITS Issuing Certifying Authority.+" p:maxPathLength="3" p:maxPathLengthAllowUnspecified="true" /> {code} The X509CredentialsAuthenticationHandler examines a User Certificate submitted with the HTTP request. The container (Tomcat, JBoss, etc.) has already verified that the Certificate comes from a trusted Certificate Authority.Generally the container is configured to only accept User Certificates issued by one of the standard Yale University CAs and not from any public sources. With this configuration, the Bean requires that the CA be specifically the Yale University ITS Certifying Authority and not one of the other CAs that the container trusts. |