ESOE Authentication Design

Enterprise Sign On Engine Technical Architecture
Written by Bradley Beddoes
September 2006

Architecture design by Bradley Beddoes
Incorporates SAML 2.0, and (L)XACML 2.0 OASIS standards

Contributions by:
Shaun Mangelsdorf
Andre Zitelli

Edited by:
Bradley Beddoes
Shaun Mangelsdorf
Andre Zitelli

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
and "OPTIONAL" in this document are to be interpreted as
described in RFC 2119

Authn Servlet

Component Lead Bradley Beddoes
Package com.qut.middleware.esoe.authn.servlet.*
Type AuthnServlet

The Authn Servlet is a control point for initial principal authentication and identification. The servlet must conform to the Servlet 2.4 specification http://jcp.org/aboutJava/communityprocess/final/jsr154/index.html, this servlet currently only supports standards compliant web browser user-agents.

This servlet MUST be of the type com.qut.middleware.esoe.authn.servlet.AuthnServlet

The servlet will be used for all requests made to https://esoe.url/logon, and utilises a cookie with a deployment configured name to determine if user-agent to web teir SSO should be enabled.

For each request that enters the servlet an object of type javax.servlet.ServletRequest is supplied by the container. This is to be stored as the value of httpRequest in a session bean implementing com.qut.middleware.esoe.authn.bean.AuthnProcessorData. An object of type javax.servlet.http.HttpServletResponse is supplied by the container. This is also to be stored as the value of httpResponse in the bean. If the SSO cookie is present and carrying a string value of true (case insensitive) then the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.automatedSSO MUST be set to false, otherwise it MUST be set to true. Finally the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.redirectTarget must be set to that specified by the name vale pair of esoeTarget, if this is not sent in the request and the value is currently null the configured default must be set.

Once the bean is fully populated the Authn Servlet MUST call the execute function on the AuthnProcessor and submit the bean as an argument.

Handled return values and actions

com.qut.middleware.esoe.authn.AuthnProcessor.result.Completed

When this success state is encountered the servlet MUST perform the following actions:

  1. The value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.redirectTarget MUST be passed to HttpServletRequest sendRedirect
  2. Should the above value be null or not exist the configured default authn completed page MUST be retieved and passed to HttpServletRequest sendRedirect

com.qut.middleware.esoe.AuthnProcessor.result.Failure

When recieving this return value the authn servlet SHOULD interrogate the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.failURL and MUST advise the user-agent to redirect to this location, no further changes to session state should occur.

Handled exceptions and actions

com.qut.middleware.esoe.AuthnProcessor.result.AuthnFailure

When recieving this exception the servlet SHOULD redirect the user-agent to the configured location for http 500 errors for this servlet.

Authn Processor

Component Lead Bradley Beddoes
Package com.qut.middleware.esoe.authn.impl.\*
Type AuthnProcessorImpl
Implemented Interfaces com.qut.middleware.esoe.authn.AuthnProcessor
Exceptions HandlerRegistrationException, AuthnFailureException

The authn processor is primarily concerned with utlisation of the authn handler pipeline. using Spring 2.0 and its IoC functionality many unique handlers are registed with the system to handle the supported methods for achieving authn with the principal. Each of these MUST implement the com.qut.middleware.esoe.authn.pipeline.Handler interface. Handlers are stored in the AuthnProcessor variable, registeredHandlers.

On initialisation the authn processor MUST verify that at least one handler has been registered, failure to have at least one handler registered MUST result in the exception com.qut.middleware.esoe.authn.AuthnProcessor.HandlerRegistrationException.

Handlers are registered in a list data structure. For every authn attempt the authn processor SHOULD traverse the entire list. Handlers may interrupt this process to perform some function, the AuthnProcessor MUST pickup where it left off when it has control handed back to it. For each handler the execute function should be called. The com.qut.middleware.esoe.authn.bean.AuthnProcessorData bean MUST be supplied to this interface. Handlers MAY add detail to this data structure but they MUST not remove any data from it. For each handler which is called the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.currentHandler must be set to value of com.qut.middleware.esoe.authn.pipeline.Handler.handlerName.

On creation of the AuthnProcessor the values of sessionDomain and sessionTokenIdentifier must be set via injection to the domain in which the session identifying cookie should live and the name the session identifying cookie should be given.

Handled return values and actions

com.qut.middleware.esoe.authn.pipeline.Handler.result.Successful

For each response of AuthnSuccessful the AuthnProcessor MUST evaluate if the value com.qut.middleware.esoe.authn.bean.AuthnProcessorData.succesfullAuthn is true, if not it should be set to true. It should then determine if any handlers remain to be evaluated in the registeredHandlers list. If they do the next handler's execute method MUST be called, additionally the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.currentHandler MUST be set to value of com.qut.middleware.esoe.authn.pipeline.Handler.handlerName.

If no further handlers are present evaluation of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.succesfullAuthn MUST occur. If this boolean is true then the the com.qut.middleware.esoe.authn.AuthnProcessorData.sessionID value should be set in a javax.servlet.Cookie with scope as the configured value for sessionDomain and name set to the value of sessionTokenName. The cookie MUST be stored in the response by calling the methods supplied in com.qut.middleware.esoe.authn.bean.AuthnProcessorData.httpResponse

AuthnProcessor MUST return com.qut.middleware.esoe.authn.AuthnProcessor.result.Successful.

If the boolean is not true then no handler has been able to identify the principal (will only occur when a catch-all handler is NOT deployed). The configured url for redirecting users to for this fault MUST be set as the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.failURL, the AuthnProcessor MUST populate and throw com.qut.middleware.esoe.authn.AuthnFailure

com.qut.middleware.esoe.authn.pipeline.Handler.result.SuccessfulNonPrincipal

For each response of SuccessfulNonPrincipal the AuthnProcessor must evaluate if any handlers remain to be evaluated in the registeredHandlers list. If they do the next handler's execute method MUST be called, additionally the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.currentHandler must be set to value of com.qut.middleware.esoe.authn.pipeline.Handler.handlerName.

If no further handlers are present evaluation of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.succesfullAuthn MUST occur. If this boolean is true then the AuthnProcessor MUST return com.qut.middleware.esoe.authn.AuthnProcessor.result.Successful.

If it is not true then no handler has been able to identify the principal (will only occur when a catch-all handler is NOT deployed). The configured url for redirecting users to for this fault MUST be set as the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.failURL, the Authn Processor MUST populate and throw com.qut.middleware.esoe.authn.AuthnFailureException

com.qut.middleware.esoe.authn.pipeline.Handler.result.NoAction

For each response of NoAction the AuthnProcessor MUST evaluate if any handlers remain to be evaluated in the registeredHandlers list. If they do the next handler's execute method MUST be called, additionally the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.currentHandler MUST be set to value of com.qut.middleware.esoe.authn.pipeline.Handler.handlerName.

If no further handlers are present evaluation of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.succesfullAuthn MUST occur. If this boolean is true then the AuthnProcessor MUST return com.qut.middleware.esoe.authn.AuthnProcessor.result.Completed.

If it is not true then no handler has been able to identify the principal (will only occur when a catch-all handler is NOT deployed). The configured url for redirecting users to for this fault MUST be set as the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.failURL, the Authn Processor MUST populate and throw com.qut.middleware.esoe.authn.AuthnFailureException

com.qut.middleware.esoe.authn.pipeline.Handler.result.Failure

If this is returned the AuthnProcessor SHOULD immediently stop processing any additional handlers. The Authn Processor MUST return com.qut.middleware.esoe.authn.AuthnProcessor.result.Failure

com.qut.middleware.esoe.authn.pipeline.Handler.result.UserAgent

If this is returned the AuthnProcessor MUST immediently stop processing any additional handlers. The Authn Processor MUST return com.qut.middleware.esoe.authn.AuthnProcessor.result.UserAgent

com.qut.middleware.esoe.authn.pipeline.Handler.result.Invalid

If this is returned the AuthnProcessor MUST immediently stop processing any additional handlers. The Authn Processor MUST return com.qut.middleware.esoe.authn.AuthnProcessor.result.Invalid

Handled exceptions and actions

com.qut.middleware.esoe.authn.exception.SessionCreationException

If this exception is thrown the AuthnProcessor should immediently stop processing any additional handlers. The configured url for redirecting users to for this fault should be set as the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.failURL

The Authn Processor SHOULD populate and throw com.qut.middleware.esoe.authn.exception.AuthnFailureException

Handlers

Handlers are responsible for actually carrying out some kind of action in regards to authn. All handlers in the authn pipeline are evaluated when an authn request takes place until either all are exhausted or a NonPassive handler decides to act.

Additionally handlers may choose to act before or after another handler in the pipeline has fully completed identification of the principal, a handler may for instance want to set a cookie regardless of the user being authenticated or not. In other situations handlers may choose to not undertake any operations if the com.qut.middleware.esoe.authn.bean.AuthnProcessorData.succesfullAuthn value is not set to true.

Types of Handlers

Principal Identifiers

Principal identifiers are directly involved in the process of authenticating a principal via some set of credentials which the organisation has chosen to trust. All principal identifiers MUST set the value of com.qut.middleware.esoe.authn.AuthnProcessorData.sessionID to a new session identifier when the principal is identified, they MUST set the value com.qut.middleware.esoe.authn.bean.AuthnProcessorData.succesfullAuthn to true and MUST return com.qut.middleware.esoe.authn.pipeline.Handler.result.Successful.

Automated

An automated handler is one which while it may send redirect statements to the user-agent does not require the user to enter any additional information to complete the identification process, for example the usage of PKI certificate installed in the users browser which is trusted. An automated handler MUST NOT complete the identification process if the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.automatedSSO is false.

Non Automated

A non automated handler is one which will require the user to explicity enter credentials in the form of username/password or supplying a specific smart card or selecting a specific card from cardspace for example.

NonPassive

A non passive handler is one which MUST take control of the users session in order to perform Authn. For example the authn processor may redirect the clients browser to some specific page containing a form element or respond back to the client with a set of specific headers to get a local application to provide some value.

Non passive handlers should be ordered carefully. Implementing a non passive handler should be done with much care to ensure that they only get invoked when environmental factors are correct. For example the user is a member of certain group or is using a specific user-agent technology. Non passive handlers which do not implement any of these checks are said to be 'catch-all' handlers. Having more then one 'catch-all' handler per stack should be very carefully thought out.

Passive

A passive handler is one which MUST NOT take control of the users session in order to perform authn. They may be simply there as a logger for example or additionally they may silently set some cookie or header value required by another handler in the pipeline or even some external application. Passive handlers can be invoked at any stage of the pipeline as necessary.

Non Principal identifiers

Non Principal identifiers are not directly involved in the process of authenticating a principal. They are used to send/recieve other information about the session. For example, they could be used to implement a CAPTCHA

NonPassive

A non passive handler is one which MUST take control of the users session in order to perform some action related to authn. For example the authn processor may redirect the clients browser to some specific page containing some information or respond back to the client with a set of specific headers to get a local application to provide some value.

Non passive handlers should be ordered very carefully. Implementing a non passive handler should be done with much care to ensure that they only get invoked when environmental factors are correct. For example the user is a member of certain group or is using a specific user-agent technology. Non passive handlers which do not implement any of these checks are said to be 'catch-all' handlers. Having more then one 'catch-all' handler per stack should be very carefully thought out.

Passive

A passive handler is one which MUST NOT take control of the users session in order to perform some action related to authn. They may be simply there as a logger for example or additionally they may silently set some cookie or header value required by another handler in the pipeline or even some external application. Passive handlers can be invoked at any stage of the pipeline as necessary.

Username/Password Handler

Component Lead Bradley Beddoes
Package com.qut.middleware.esoe.authn.pipeline.handlers.\*
Type UsernamePasswordHandler
Implemented Interfaces com.qut.middleware.esoe.authn.pipeline.Handler
Exceptions SessionCreationFailureOnSuccessfulAuthn

The UsernamePasswordHandler will allow clients to submit their username and password in a textual form to identify themselves to the system, the most popular of methods currently in use today.

This handler is of type NonAutomated, NonPassive, additionally it is catch-all.

If com.qut.middleware.esoe.authn.bean.AuthnProcessorData.succesfulAuthn is already set to true the handler MUST return com.qut.middleware.esoe.authn.pipeline.Handler.result.NoAction

The handler looks for a post request coming from the user. If this is not present in the request the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.failURL must be set to the default value and com.qut.middleware.esoe.authn.pipeline.Handler.result.UserAgent returned.

The form SHOULD be created with a method of post, a target of https://esoe.url/logon a name of esoeauthn_uphandler and autocomplete set to off. The form MUST expose two input fields, the first named esoeauthn_user of size 20 and type text, the second named esoeauthn_pw of size 20 and type password.

If the request form is considered to be invalid the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.failURL MUST be set to the configured location for failed authentication attempts. Generally this will be the same page as used for entering esoeauthn_user and esoeauth_pw. Name value pairs of 'esoerc=failauthn' and 'esoehandler=<name#>-<version#>' should be appended where name# is the name of the handler and version# is the current version of the handler. Once this value is set the exception com.qut.middleware.esoe.authn.exception.AuthnFailureException MUST be populated and thrown.

When the user submits this form the Handler MUST traverse the list of authenticator objects which have been injected into it by calling each authenticate function in turn and passing the values of esoeauthn_user and esoeauthn_pw as arguments. These authenticators MUST implement the com.qut.middleware.esoe.authn.pipeline.Authenticator interface.

Any exception returned from the authenticator MUST be caught by the Handler. If an exception is caught or the value com.qut.middleware.esoe.authn.pipeline.Authenticator.result.Failure is returned then the following MUST occur:
The value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.failURL MUST be set to the configured location for failed authentication attempts. Generally this will be the same page as used for entering esoeauthn_user and esoeauth_pw. Name value pairs of 'esoerc=failauthn' and 'esoehandler=<name#>-<version#>' should be appended where name# is the name of the handler and version# is the current version of the handler. Once this value is set the value com.qut.middleware.esoe.authn.pipeline.Handler.result.Failure MUST be returned.

If the result of an authenticate call is com.qut.middleware.esoe.authn.pipeline.Authenticator.result.Successful the handler SHOULD generate a session identifier using the SAML2lib-j Identifier Generator. Once the session has been created a call to the Sessions Processor creation interface should be made. The value of the generated session identifier and the value of esoeauthn_user should be supplied as arguments.

If the result of this call is com.qut.middleware.esoe.sessions.Create.result.SessionCreated the session identifier value MUST be set in com.qut.middleware.esoe.authn.AuthnProcessorData.sessionID

Any exception returned from creating a session MUST be caught by the Handler and the exception com.qut.middleware.esoe.authn.pipeline.SessionCreationFailureOnSuccessfulAuthn populated and thrown.

If the Handler is satisified that all is successful the value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.succesfullAuthn MUST be set to true. The value com.qut.middleware.esoe.authn.pipeline.Handler.result.Successful MUST be returned.

If the result of an authenticate call is com.qut.middleware.esoe.authn.pipeline.Authenticator.result.Failure then all other authenticators present in the list should be called in turn, once all authenticators are exhausted the value com.qut.middleware.esoe.authn.pipeline.Handler.result.Failure MUST be returned.

SPNEGO Handler

Component Lead Andre Zitelli
Package com.qut.middleware.esoe.authn.pipeline.handlers.\*
Type SPNEGOHandler
Implemented Interfaces com.qut.middleware.esoe.authn.pipeline.Handler
Exceptions

This handler is of type Automated, Passive.

The handler accepts POST requests from the client and performs the following actions:

If the value of AuthnProcessorData.automatedSSOEnabled is false, no further processing is undertaken and the Handler returns Handler.result.NoAction;

If auto SSO is enabled, the handler will look for a customised user-agent field containing the string configured in esoe.config:spnegoHandler.spnegoUserAgentID. If the string is present the handler will send a HTTP 401 WWW-Authenticate: Negotiate response back to the browser. This informs SPNEGO capable browsers to use the SPNEGO Negotiate protocol.

If the browser responds to the Authenticate response, the handler will attempt to process the SPNEGO token sent in the browser request by calling com.qut.middleware.esoe.auth,pipeline.authenticator.SPNEGOAuthenticator.execute.

If the SPNEGO data is valid and a context can be established with the Kerberos AS, the Handler will attempt to create the user session. If the session is sucessfully created, Handler.result.Successful is returned. If the seesion cannot be created, Handler.result.Invalid is returned.

If the SPNEGO data is invalid, or a context cannot be established with the kerberos AS to authenticate the principal, Handler.result.NoAction is returned.

Authenticators

Component Lead Bradley Beddoes
Package com.qut.middleware.esoe.authn.pipeline.authenticators.\*

Each handler delegates its authentication functionality to an Authenticator, this enables a single handler for example the username/password handler to Authenticate against a number of backend systems as required by a particular deployment. Authenticators may be presented as a single instance or as a list of instances, each of which can be evaluated in turn until success is found or all options are exhausted, authentication implementation is specific to a Handler and is left upto the developer to determine implementation. All authenticator interfaces MUST live under com.qut.middleware.esoe.auth.pipeline and implementations MUST live under com.qut.middleware.esoe.auth.pipline.authenticator. Reuse wherever possible is encouraged.

Also available in: HTML TXT