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
.
Enterprise Sign On Engine

ESOE authoritative data store
One of the core components to the operation of the ESOE is the central repository of authoritative data. This database stores all the details required to build the metadata representation of the core system and its associated service providers in network. It also contains a record of each new authentication event which successfully takes place on the system as well as records of each service that is visited for clients in each session. This allows fine grained security data to obtained easily with the added benefit of data mining activities to gain a picture of where clients are traversing the system.
This data is managed by the ESOE Manager system which is documented elsewhere.
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:
- The value of com.qut.middleware.esoe.authn.bean.AuthnProcessorData.redirectTarget MUST be passed to HttpServletRequest sendRedirect
- 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.
SSO Servlet
| Component Lead |
Bradley Beddoes |
| Package |
com.qut.middleware.esoe.sso.servlet.* |
| Type |
SSOServlet |
| Implemented Interfaces |
N/A |
The SSO Servlet is a control point for SSO requests. 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.
The servlet will be used for all requests made to https://esoe.url/sso
The SSO Servlet SHOULD implement the saml-bindings-2.0 HTTP POST Binding as its primary method of communication with the SPEP.
Messages are encoded for use with this binding by encoding XML into an HTML form control and are transmitted using the HTTP POST method. The SPEP generated SAML <AuthnRequest> is form-encoded by applying the base-64 encoding rules to the XML representation of the message and placing the result in a hidden form control within a standard html form. The form control MUST be named SAMLRequest. The SSO Servlet MUST decode this value.
A bean which implements the interface com.qut.middleware.esoe.sso.bean.SSOProcessorData must be passed by the servlet to the SSO Processor, it MUST be initalised by the servlet. This bean MAY contain value of the users session identifier. Incoming requests from the user-agent will provide session identifiers, in this case in the form of cookies. The identity of the cookie to be utilised is configurable, if present its value MUST be stored in com.qut.middleware.esoe.sso.bean.SSOProcessorData.sessionID. Additionally any SAML request which has been recieved MUST be stored in com.qut.middleware.esoe.sso.bean.SSOProcessorData.samlRequestDocument. For each request that enters the servlet an object of type javax.servlet.http.HttpServletRequest is supplied by the container as is an object of type javax.servlet.http.HttpServletResponse. These are to be stored as the value of httpRequest and httpResponse respectively in com.qut.middleware.esoe.sso.bean.SSOProcessorData
Once the servlet now MUST call the SSO Processor execute function.
Responding to the SPEP
The SSO Servlet should determine a valid binding for the SPEP favoring the SAML POST binding.
Messages are encoded for use with the POST binding by encoding com.qut.middleware.esoe.sso.bean.SSOProcessorData.samlResponseDocument into an HTML form control and are transmitted using the HTTP POST method. The generated SAML <Response> is form-encoded by applying the base-64 encoding rules to the XML representation of the message and placing the result in a hidden form control within a standard html form. The form control MUST be named SAMLResponse. A response document should be sent back to the http user-agent. A javascript event should be utilised to POST the document to com.qut.middleware.esoe.sso.bean.SSOProcessorData.responseEndpoint after 2 seconds.
Handled return values and actions
com.qut.middleware.esoe.sso.SSOProcessor.result.SSOGenerationSuccessful
The servlet should respond to the SPEP using its response mechanism.
com.qut.middleware.esoe.sso.SSOProcessor.result.LogoutSuccessful
Should not be handled by this servlet
com.qut.middleware.esoe.sso.SSOProcessor.result.ForcePassiveAuthn
The servlet should now respond to the SPEP using its response mechanism.
com.qut.middleware.esoe.sso.SSOProcessor.result.ForceAuthn
The user-agent MUST be redirected to the configured Authn provider for the user-agent on the ESOE, again currently only supporting standards compliant web browser user-agents, the url (incl post data) being requested at the Authn Filter MUST be attached using a name value pairing of esoeTarget=<url>
Handled exceptions and actions
com.qut.middleware.esoe.sso.exception.InvalidSessionIdentifierException
This exception MUST have all sessionIdentifiers (cookies in this case) stripped from the user-agent.
The servlet should now respond to the SPEP using its response mechanism.
Authentication Authority Processor
| Component Lead |
Bradley Beddoes |
| Package |
com.qut.middleware.esoe.sso.impl.* |
| Type |
SSOProcessorImpl |
| Implemented Interfaces |
com.qut.middleware.esoe.sso.SSOProcessor |
| Exceptions |
InvalidSessionIdentifierException |
The SSOProcessorImpl should firstly validate the [Request]
Any invalidly generated request must create and throw com.qut.middleware.esoe.sso.InvalidRequest
The value of <Issuer> should be retrieved and stored at com.qut.middleware.esoe.sso.bean.SSOProcessorData.descriptorID. The value of AssertionConsumerServiceIndex should be retrieved and stored at com.qut.middleware.esoe.sso.bean.SSOProcessorData.responseEndpointID. This value along with the descriptorID MUST be sent to the SPEP processor to determine the URL of the SPEP endpoint to respond to. The value of com.qut.middleware.esoe.sso.bean.SSOProcessorData.responseEndpoint should be set as the response value. If this operation causes an exception it should be caught and com.qut.middleware.esoe.sso.InvalidRequest created and thrown.
Once this occured the value of <NameIDPolicy> AllowCreate MUST be determined. Once this is the case one of three actions MUST be taken:
- com.qut.middleware.esoe.sso.bean.SSOProcessorData.sessionID is not null
- Fall through to additional logic processing
- If the value is 'True'
- Return com.qut.middleware.esoe.sso.SSOProcessor.result.ForceAuthn
- If the value is 'False'
- A SAML [Response] MUST be created, the value of <Status>, <StatusCode> MUST be set to urn:oasis:names:tc:SAML:2.0:status:AuthnFailed, the generated Response MUST be stored at com.qut.middleware.esoe.sso.bean.SSOProcessorData.samlResponseDocument.
- Return com.qut.middleware.esoe.sso.SSOProcessor.result.ForcePassiveAuthn
The SSOProcessorImpl MUST now validate sessionIdentifier against the com.qut.middleware.esoe.sessions.Query.queryAuthnSession query component to ensure that it has been issued by the ESOE Authn Processor and is currently valid by requesting a com.qut.middleware.esoe.sessions.Principal. Any request that fails to be validated against the local session cache after having presented what it considered to be a valid session identifer MUST result in an com.qut.middleware.esoe.sso.exception.InvalidSessionIdentifierException exception being thrown.
If the value of ForceAuthn in the request is set to 'true' one of three actions MUST be taken
- The value of IsPassive is set to true AND the principal details indicate they last authenticated more then the configured minimal time in the past (default of 60 seconds)
- A SAML [Response] MUST be created, the value of <Status>, <StatusCode> MUST be set to urn:oasis:names:tc:SAML:2.0:status:AuthnFailed, the generated Response MUST be stored at com.qut.middleware.esoe.sso.bean.SSOProcessorData.samlResponseDocument.
- Return com.qut.middleware.esoe.sso.SSOProcessor.result.ForcePassiveAuthn
- The value of IsPassive is set to false AND the principal details indicate they last authenticated more then the configured minimal time in the past (default of 60 seconds)
- Return com.qut.middleware.esoe.sso.SSOProcessor.result.ForceAuthn
If the principal has not previously had an entry recorded for the SPEP being accessed in com.qut.middleware.esoe.sessions.Principal.activeEntities this indentifier should be added to the principal by calling the com.qut.middleware.esoe.sessions.Update.updateEntityList update component, supplying the sessionIdentifier and descriptorID as values.
A 10 byte SHA1 hash should be generated by the Identity Generator and added to the principal by calling the com.qut.middleware.esoe.sessions.Update.updateEntitySessionIdentifierList update component, supplying the sessionIdentifier, descriptorID and generated samlAuthnSessionIndex as values.
Details about the com.qut.middleware.esoe.sessions.Principal should now be refreshed by using the valid sessionIdentifer with the com.qut.middleware.esoe.sessions.Query.queryAuthnSession query component.
If the request has passed all processing logic and deemed to be valid an AuthnStatement must be created by generating a base SAML Statement additionally
AuthnInstant MUST be set to the UTC value of time the assertion was created with no time zone information.
SessionIndex SHOULD be set to the value generated for the current session
SessionNotOnOAfter SHOULD be set to the UTC value of the time the assertion was generated plus the configured time skew allowance (set at default of 60 seconds)
<Subject> MUST be set and MUST contain a <NameID> element. The value of this element SHOULD be set to com.qut.middleware.esoe.sessions.Principal.samlAuthnIdentifier
<AuthnContext> MUST be set and MUST contain an <AuthenticatingAuthority> its value MUST be set to https://esoe.url/logon
The statement MUST be wrapped in a SAML Assertion
The assertion MUST be wrapped in a SAML Response
The completed SAML response should be stored at com.qut.middleware.esoe.sso.bean.SSOProcessorData.samlResponseDocument
The processor should now return control to the SSO Servlet with a value of com.qut.middleware.esoe.sso.SSOProcessor.result.SSOGenerationSuccessful.
Logout Servlet
| Component Lead |
Andre Zitelli |
| Package |
com.qut.middleware.esoe.logout.servlet.* |
| Type |
LogoutServlet |
| Implemented Interfaces |
N/A |
The Logout Servlet is a control point for Logout requests. 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.
The servlet will be used for all requests made to https://esoe.url/logout
A bean which implements the interface com.qut.middleware.esoe.logout.bean.LogoutProcessorData must be passed by the servlet to the Logout Processor, it MUST be initalised by the servlet. This bean MAY contain value of the users session identifier. Incoming requests from the user-agent will provide session identifiers, in this case in the form of cookies. The identity of the cookie to be utilised is configurable, if present its value MUST be stored in com.qut.middleware.esoe.sso.bean.SSOProcessorData.sessionID. For each request that enters the servlet an object of type javax.servlet.http.HttpServletRequest is supplied by the container as is an object of type javax.servlet.http.HttpServletResponse. These are to be stored as the value of httpRequest and httpResponse respectively in com.qut.middleware.esoe.sso.bean.SSOProcessorData
Once the servlet now MUST call the Logout Processor execute function.
Handled return values and actions
com.qut.middleware.esoe.logout.LogoutProcessor.result.LogoutSuccessful
Once the logout is deemed to be completed the Logout Servlet should determine if 'disablesso' was presented by the user of the system. If it is present the Logout Servlet SHOULD create a cookie with a scope of https://esoe.url/
and named as configured for ESOE disablesso cookie. Its value should simply be set to 'disablesso'. The cookie SHOULD be stored in the response by calling the methods supplied in com.qut.middleware.esoe.logout.bean.LogoutProcessorData.httpResponse
The Logout Servlet must determine where to direct the principal. If the value of esoelogout_response was supplied the implementation MAY choose to redirect the user to location configured for the supplied identifier by setting the URL as the value of com.qut.middleware.esoe.logout.bean.LogoutProcessorData.responseURL. Should the implementation not wish to honor this value or it is not supplied com.qut.middleware.esoe.logout.bean.LogoutProcessorData.responseURL should be set to the configured default for the ESOE.
The user-agent MUST be redirected to the configured URL for successful logout requests for the ESOE.
Handled exceptions and actions
com.qut.middleware.esoe.logout.exception.InvalidSessionIdentifierException
This exception MUST have all sessionIdentifiers (cookies in this case) stripped from the user-agent.
The user-agent MUST be redirected to the configured URL for failed logout requests for the ESOE.
com.qut.middleware.esoe.logout.exception.InvalidLogoutRequestException
The user-agent MUST be redirected to the configured URL for failed logout requests for the ESOE.
Logout Processor
| Component Lead |
Andre Zitelli |
| Package |
com.qut.middleware.esoe.logout.impl.* |
| Type |
LogoutProcessorImpl |
| Implemented Interfaces |
com.qut.middleware.esoe.sso.SSOProcessor |
| Exceptions |
InvalidSessionIdentifierException |
The LogoutProcessorImpl operates on a form post event coming from the principal.
The form SHOULD be created with a method of post, a target of https://esoe.url/logout
a name of esoesso_logout and autocomplete set to off. The form MUST expose an input field named disablesso, type checkbox. The form creator MAY choose to implement the hidden field esoelogout_response, where the value of this field is a numeric value representing the prefered logout page to respond to as configured for the LogoutProcessorImpl. This allows the ESOE to be utilised for multiple logout pages within an enterprise should the single logout portal not be sufficent.
If the request form is considered to be invalid the LogoutProcessorImpl MUST populate and throw the exception com.qut.middleware.esoe.sso.exception.InvalidLogoutRequestException
The LogoutProcessorImpl MUST validate the com.qut.middleware.esoe.sso.bean.SSOProcessorData.sessionID value against the com.qut.middleware.esoe.sessions.Query.queryAuthnSession query component to ensure that it has been issued by the ESOE Authn Processor and is currently valid by requesting com.qut.middleware.esoe.sessions.Principal. Any request that fails to be validated against the local session cache after having presented what it considered to be a valid sessionIdentifer MUST result in a com.qut.middleware.esoe.sso.InvalidSessionIdentifierException exception being thrown.
Each descriptorID for the com.qut.middleware.esoe.sessions.Principal.activeEntities list SHOULD be traversed.
For each descriptorID
A request supplying the descriptorID should be sent to the SPEP processor endpoints for single logout.
For each effected descriptorID/endPoint combination a LogoutRequest MUST be created by generating a base [Request] and addtionally specifying:
NotOnOrAfter SHOULD be set to the UTC value of the current system time plus the configured time skew allowance (set at default of 60 seconds)
Reason SHOULD be set to "https://esoe.url/logout"
<NameID> - This value MUST be set to the principals samlAuthnIdentifier
<SessionIndex> - This value MUST be set to the sessionIndex of the session being terminated.
For each request generated the injected IDPSSOWS instance single logout service should be called and the generated SAML message and currently processing endpoint supplied. A SAML response document MUST be returned. The SAML response contained should be validated and a status of urn:oasis:names:tc:SAML:2.0:status:Success assured. Where these conditions are not met or an exception is returned by IDPSSOWS a bean implementing com.qut.middleware.esoe.logout.bean.FailedLogout must be created. The SAML request document must be stored at com.qut.middleware.esoe.logout.bean.FailedLogout.requestDocument, the current endpoint at com.qut.middleware.esoe.logout.bean.FailedLogout.endPoint. This bean should be supplied to the injected failed logout monitor.
The session information should be cleaned up on the ESOE by calling com.qut.middleware.esoe.sessions.Terminate.terminateSession terminate component and supplying the session identifier.
The processor should now return control to the Logout Servlet with a value of com.qut.middleware.esoe.sso.LogoutSuccessful.
Failed logout Monitor
The failed logout monitor consistently looks at a repository of com.qut.middleware.esoe.logout.bean.FailedLogout beans. Once it reaches the end of the repository it MUST immediently start at the beginning and work its way back through again attempting to deliver logouts to SPEPs. On startup the monitor is to be created in its own thread, this thread MUST continuously stay active until the shutdown of the system. Should it fail in some way it MUST be automatically recovered by the system.
For each bean stored in the repository the generated document stored at com.qut.middleware.esoe.logout.bean.FailedLogout.requestDocument should be regenerated with updated timestamps and signatures to avoid time problems and the new document re-stored at this location. The injected IDPSSOWS instance single logout service should now be called with com.qut.middleware.esoe.logout.bean.FailedLogout.requestDocument and com.qut.middleware.esoe.logout.bean.FailedLogout.endPoint supplied. A SAML response document MUST be returned. The SAML response contained should be validated and a status of urn:oasis:names:tc:SAML:2.0:status:Success assured. If this is the case the bean is ejected from the local repository.
If this check fails the value of com.qut.middleware.esoe.sso.bean.FailedLogout.TimeStamp should be evaluated. If it is older then the time configured as a maximum (default of 24hrs) the bean is ejected from the local repository.
Where these conditions are not met or an exception is returned by IDPSSOWS the bean should remain in the local repository.
External components will supply additional failed logout to be added to the repository at random intervals. When they are supplied the repository MUST be locked for both read and write access while the new data is added. For each bean placed into the repository the value of com.qut.middleware.esoe.logout.bean.FailedLogout.TimeStamp must be set to the current system time.
Web Services Interfaces
| Component Lead |
Shaun Mangelsdorf |
| Package |
com.qut.middleware.esoe.ws.* |
Web service interfaces in the ESOE are created using the Axis2, the ESOE makes use of RAWXMLInputOutput to ensure it gets the lowest level access possible to the creation and handling of the SOAP envelope.
All web serivce endpoints in the system are exposed using the Axis2 <-> Spring 2.0 IoC wiring interfaces to allow for customisable deployments.
WSClient
| Component Lead |
Shaun Mangelsdorf |
| Package |
com.qut.middleware.esoe.ws.clients.WSClient |
| Exceptions |
WSClientException |
The WSClient is responsible for communicating to SPEP's using web services when the IDP needs to provide them some kind of update.
This interface is only used to connect to SPEP, it does not specify an endpoint on which to receive incoming requests.
At the current time it implements functions for initiating an authz cache clear and single logout. These functions MUST be supplied with a valid SAML request document and a valid endpoint URI to connect to. The WSClient is solely responsible for handling all SOAP interactions and envelope wrapping/unwrapping.
Should the WSClient at any stage of communication encounter an exception or error state it MUST wrap this error or exception in WSClientException and throw for the caller to deal with.
WSProcessor
WSProcessor is the implementation of all logic for web services interfaces that the ESOE exposes for SPEP's to connect to. It is configured as the service class for Axis2 services.xml file and currently exposes three core functions.
Attribute Authority
This endpoint is responsible for receiving requests from the SPEP, this webservice does not initiate requests.
This service is accessible at the URL https://esoe.url/axis2/services/esoe/attributeAuthority
Using Spring, a processor will be injected into this descriptor, this object MUST implement the com.qut.middleware.esoe.aa.AttributeAuthorityProcessor interface. A bean which implements the interface com.qut.middleware.esoe.aa.bean.AAProcessorData interface must be created and SAML request object stored at com.qut.middleware.esoe.aa.bean.AAProcessorData.requestDocument. Once generated the execute function on the injected AttributeAuthorityProcessor MUST be called with the created bean as an argument.
Handled return values and actions
com.qut.middleware.esoe.aa.om.qut.middleware.esoe.aa.AttributeAuthorityProcessor.result.Successful
The value stored at com.qut.middleware.esoe.aa.bean.AAProcessorData.responseDocument should be wrapped in a SOAP response and sent back to the requestor.
Handled exceptions and actions
com.qut.middleware.esoe.aa.exception.InvalidRequestException
The value stored at com.qut.middleware.esoe.aa.bean.AAProcessorData.responseDocument should be wrapped in a SOAP response and sent back to the requestor.
Policy Decision Point
This endpoint is responsible for receiving requests from the SPEP, this webservice does not initiate requests.
This service is accessible at the URL https://esoe.url/axis2/services/esoe/policyDecisionPoint
Using Spring, a processor for lxacml requests will be injected into this descriptor, this object MUST implement the com.qut.middleware.esoe.pdp.AuthorizationProcessor interface. A bean which implements the interface com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData interface must be created. The SAML request document MUST be unwrapped from the SOAP message and stored at com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData.requestDocument. Once generated the execute function on the injected AuthorizationProcessor MUST be called with the created bean as an argument.
Handled return values and actions
com.qut.middleware.esoe.pdp.AuthorizationProcessor.result.Successful
The value stored at com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData.responseDocument should be wrapped in a SOAP response and sent back to the requestor.
Handled exceptions and actions
com.qut.middleware.esoe.pdp.exception.InvalidRequestException
The value stored at com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData.responseDocument should be wrapped in a SOAP response and sent back to the requestor.
com.qut.middleware.esoe.pdp.exception.InvalidPrincipalException
The value stored at com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData.responseDocument should be wrapped in a SOAP responseand sent back to the requestor.
SPEP Startup
This endpoint is responsible for receiving requests from the SPEP, this webservice does not initiate requests.
This service is accessible at the URL https://esoe.url/axis2/services/esoe/spepStartup
Using Spring, a processor for esoe requests will be injected into this descriptor, this object MUST implement the com.qut.middleware.esoe.spep.SPEPProcessor interface. A bean which implements the interface com.qut.middleware.esoe.spep.bean.SPEPProcessorData interface must be created and contain the SAML request object. Once generated the execute function on the injected ESOEProcessor MUST be called with the created bean as an argument.
Handled return values and actions
The startup service will not return a value, if no exception is thrown the value stored at com.qut.middleware.esoe.spep.bean.SPEPProcessorData.responseDocument should be wrapped in a SOAP evelope and HTTP document and sent back to the requestor.
Handled exceptions and actions
com.qut.middleware.esoe.spep.exception.CacheUpdateFailureException
The value stored at com.qut.middleware.esoe.spep.bean.SPEPProcessorData.responseDocument should be wrapped in a SOAP evelope and HTTP document and sent back to the requestor.
com.qut.middleware.esoe.spep.exception.InvalidRequestException
The value stored at com.qut.middleware.esoe.spep.bean.SPEPProcessorData.responseDocument should be wrapped in a SOAP evelope and HTTP document and sent back to the requestor.
com.qut.middleware.esoe.spep.exception.NoSuchSPEPException
The value stored at com.qut.middleware.esoe.spep.bean.SPEPProcessorData.responseDocument should be wrapped in a SOAP evelope and HTTP document and sent back to the requestor.
Delegated AuthN
This endpoint is responsible for receiving requests from the delegated Authn handlers with unique knowledge of some particular protocol, this webservice does not initiate requests.
This service is accessible at the URL https://esoe.url/axis2/services/esoe/delegatedAuthn
Further design doco to follow.
Attribute Authority Processor
| Component Lead |
Shaun Mangelsdorf |
| Package |
com.qut.middleware.esoe.aa.impl.* |
| Type |
AttributeAuthorityProcessorImpl |
| Implemented Interfaces |
com.qut.middleware.esoe.aa.AttributeAuthorityProcessor |
| Exceptions |
InvalidRequestException, InvalidPrincipalException |
Verify the supplied value of com.qut.middleware.esoe.aa.bean.AAProcessorData.requestDocument. Any invalid request MUST set com.qut.middleware.esoe.aa.bean.AAProcessorData.responseDocument to a base response with <Status> of urn:oasis:names:tc:SAML:2.0:status:Requestor. No AttributeStatement is generated for this failure case and no further processing should be undertaken except to create and throw com.qut.middleware.esoe.aa.exception.InvalidRequestException
The value of <Issuer> should be retrieved and stored at com.qut.middleware.esoe.aa.bean.AAProcessorData.descriptorID.
The value of <Subject> should be determined and stored against com.qut.middleware.esoe.aa.bean.AAProcessorData.subjectID.
The subjectID SHOULD be used with the the com.qut.middleware.esoe.sessions.Query.querySAMLSession query component to retrieve a com.qut.middleware.esoe.sessions.Principal. If the request throws an exception this should be caught. It MUST be considered a failure, the AAP MUST set com.qut.middleware.esoe.aa.bean.AAProcessorData.responseDocument to a base response with <Status> of urn:oasis:names:tc:SAML:2.0:status:Authn. No AttributeStatement is generated for this failure case and no further processing should be undertaken except to create and throw com.qut.middleware.esoe.aa.exception.InvalidRequestException
Once the principal object is successfully retrieved the processor should evaluate com.qut.middleware.esoe.sessions.bean.IdentityData.attributes. At the present time the processing model here is fairly simple. In the future the Attribute Authority may be extended to support privacy for users and perhaps an extensible pipeline architecture for responding with attributes. Addtionally the aatribute authority does not currently impose the SAML spec limitations correctly especially relating to only returning equal values for <AttributeValues> which are specified and only returning <Attributes> which are specified. This functionality will also be added later, for now all SPEP get all attribute details.
The attribute authority currently only supports the basic attribute profile.
For each key stored in com.qut.middleware.esoe.sessions.bean.IdentityData.attributes a check should be made to ensure the vector located in the associated com.qut.middleware.esoe.sessions.bean.IdentityAttribute.values has at least one element. If this is the case <saml:Attribute> should be created. NameFormat SHOULD always be set to urn:oasis:names:tc:SAML:2.0:attrname-format:basic. Name SHOULD be set to the current key. An <saml:AttributeValue> should now be created, for each value stored in the vector. type for this element MUST be set to the matching XML type for the corresponding value of com.qut.middleware.esoe.sessions.bean.IdentityAttribute.type (ie For 'string' type="xs:string").
Where no attributes exist an empty AttributeStatement should be returned.
An AttributeStatement MUST now be created.
Once complete the value com.qut.middleware.esoe.aa.AttributeAuthorityProcessor.result.Successful MUST be returned
Creating AttributeStatement
Once all the <saml:Attribute> elements have been created for the specified com.qut.middleware.esoe.sessions.Principal an <AttributeStatement> MUST be created and embed all the generated values for <saml:Attribute>
SAML Wrappers
An [assertion] MUST be created and the <AttributeStatement>. embedded inside.
A base [response] MUST be created with <Status> information set as detailed by the request processing, it should contain the generated <Assertion>.
Once successfully created the response should be stored at com.qut.middleware.esoe.aa.bean.AAProcessorData.responseDocument.
PDP Processor (LXACML)
| Component Lead |
Andre Zitelli |
| Package |
com.qut.middleware.esoe.pdp.* |
The current design of the PSP is based on a simplified XACML 2.0 standard which we have dubbed 'Lightweight eXtensible Access Control Markup Language (LXACML)', all requests and responses are wrapped up in the (L)XACML 2.0 profile for SAML 2.0 for all transports and to ensure properties such as message integrity. We decided to implement a streamlined version of XACML 2.0 to meet specific business requirements, there will also be fully XACML 2.0 compliant offering in the open source version.
(L)XACML authorization policies are XML documents that define three top-level policy elements: <Rule>, <Policy> and <PolicySet>.
The <Rule> element contains a Boolean expression that can be evaluated in isolation, but that is not intended to be accessed in isolation. So, it is not intended to form the basis of an authorization decision by itself. The <Policy> element contains a set of <Rule> elements and a specified procedure for combining the results of their evaluation. It is the basic unit of policy used and so it is intended to form the basis of an authorization decision. The <PolicySet> element contains a set of <Policy> or other <PolicySet> elements and a specified procedure for combining the results of their evaluation. It is the standard means for combining separate policies into a single combined policy.
For our initial purposes the PAP will be a simplified web form which will take an XML file already encoded in the schema outlined below, this will be validated and pushed up to the PDP which will live as a component inside the ESOE. Our PDP will initially only implement one rule combining algorithm Deny-overrides. If a single <Rule> or <Policy> element is encountered that evaluates to Deny, then, regardless of the evaluation result of the other <Rule> or <Policy> elements in the applicable policy, the combined result is Deny. The default state of the authorization engine is to Deny, this can be configured to a default state of Permit by administrators if required but changing the default state should be undertaken with care.
Reading Requirements
Authorization Terms
Access - Performing an action
Access control - Controlling access in accordance with a policy
Action - An operation on a resource
Applicable policy - The set of policies and policy sets that governs access for a specific decision request
Attribute - Characteristic of a subject, resource, action or environment that may be referencedin a predicate or target
Authorization decision - The result of evaluating applicable policy. A function that evaluates to "Permit" or "Deny"
Bag - An unordered collection of values
Condition - An expression of predicates. A function that evaluates to "True", "False" or "Indeterminate"
Conjunctive sequence - a sequence of predicates combined using the logical 'AND' operation
Context - The canonical representation of a decision request and an authorization decision
Context handler - The system that converts decision requests in the native request format to the XACML canonical form and converts authorization decisions in the XACML canonical form to the native response format
Decision - The result of evaluating a rule, policy or policy set
Disjunctive sequence* - a sequence of predicates combined using the logical 'OR' operation
Effect - The intended consequence of a satisfied rule (either "Permit" or "Deny")
Policy - A set of rules, an identifier for the rule-combining algorithm and (optionally) a set of obligations. May be a component of a policy set
*Policy administration point (PAP) - The system that creates a policy or policy set
Policy-combining algorithm - The procedure for combining the decision and obligations from multiple policies
Policy set - A set of policies, other policy sets, a policy-combining algorithm and (optionally) a set of obligations. May be a component of another policy set
Predicate - A statement about attributes whose truth can be evaluated
Resource - Data, service or system component
Rule - A target, an effect and a condition. A component of a policy
Rule-combining algorithm - The procedure for combining decisions from multiple rules
Subject - An actor whose attributes may be referenced by a predicate
Target - The set of decision requests, identified by definitions for resource, subject and action, that a rule, policy or policy set is intended to evaluate
authzPolicy Cache Processor
| Component Lead |
Andre Zitelli |
| Package |
com.qut.middleware.esoe.pdp.cache.impl.* |
| Type |
PolicyCacheProcessorImpl |
| Implemented Interfaces |
com.qut.middleware.esoe.pdp.cache.PolicyCacheProcessor |
The authzPolicy cache processor is perhaps one of the most critical elements in the entire system, it is responsible for continuously monitoring the database for changes to policy items and advising to all effected SPEP's that they should drop their caches immediently.
Binding for communicating with SPEP
The ESOE should implement the saml-bindings-2.0 SAML over SOAP over HTTP Binding as their method of communication with the SPEP.
The ESOE should only ever send authorization responses over backchannel communication.
The ESOE should not set any additional HTTP header information.
The SAML response should be appropriately wrapped in a SOAP envelope and delivered to the HTTP endpoint for the SPEP.
Generating initial cache state
The authZ Cache processor MUST execute as follows:
On startup the processor is to be created in its own thread, this thread MUST continuously stay active until the shutdown of the system. Should it fail in some way it MUST be automatically recovered by the system.
When the processor is executed it SHOULD using iBatis database stack connect to the ESOE authorative data store and a query should be issued agaist the database to determine the most highest value of SEQID from SERVICE_POLICIES_STATE this value should be stored as prevSequenceID
The processor now MUST obtain an exclusive lock on the PDP wide authzCache object. For each descriptorID located in the table SERVICE_POLICIES a vector of type java.util.Vector should be created. For each descriptorID its (L)XACML policies stored in the database MUST be parsed into language specific objects representing the <Policy> element. Each policy object should be stored in the vector. Once all elements are parsed the vector should be stored in the authzCache with a key of descriptorID. The exclusive lock SHOULD now be released.
Once the cache has been generated the processor MUST advise SPEPs that it has built a new cache.
For each descriptorID:
A request supplying the descriptorID should be sent to the SPEP processor endpoint resolver for cache clear to retrieve a vector of endpoints to communicate with.
For each effected descriptorID/endpoint combination a ClearAuthzCacheRequest SHOULD be created by generating a base [Request] with the addition of the following:
Reason MUST be set to the string of "ESOE advises complete rebuild of central authzPolicy cache"
<Extenstions> MUST be present and its value MUST be set to be the set to the <GroupTarget> for this entity as follows:
The value of <GroupTargetID> SHOULD be set to the corresponding value of the entities <Policy> / <Target> from the authzCache. A new <AuthzTarget> element should be set to the corresponding value of each defined <Rule> / <Target>. Where <Rule> has been created with no <Target> value the value of <Policy> / <Target> should be substituted. This MUST only occur once, subsequent <Rules> that DO NOT define a <Target> can be ignored.
For each request generated the spring injected ESOEWS instance clear cache service should be called and the generated SAML message and currently processing endpoint supplied. A SAML response document MUST be returned. The SAML response contained should be validated and a status of urn:oasis:names:tc:SAML:2.0:status:Success assured. Where these conditions are not met or an exception is returned by ESOWES a bean implementing com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate must be created. The SAML request document must be stored at com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate.requestDocument, the current endpoint at com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate.endPoint. This bean should be supplied to the Spring IoC injected failed authz cache monitor.
Maintaining Cache State
Once the initial configuration has been setup the authzPolicy cache processor must poll the database using iBatis database stack at configured time intervals (default 60 seconds) for changes to the table SERVICE_POLICIES_STATUS. This is achieved by requesting the maximum value of SEQID and comparing it against prevSequenceID
If the values are in sync then no further action is to be taken and the processor is to sleep for another configured time interval.
If the returned value is greater the processor MUST select all policies and associated descriptorID's from SERVICE_POLICIES_STATE that have a SEQID value greater then prevSequenceID, the maximum value of SEQID from this request gets set as the new value of prevSequenceID.
For each modified descriptorID:
The value of POLACTION MUST be checked. For a value of 'U' (Update) the processor must parse the associated policy stored in the table SERVICE_POLICIES into LXACML language specific objects. The current cache should be checked to determine if a policy with the current policyID exists for the descriptorID, if it does then it must be ejected and this new version added. If it doesn't contain the DescriptorID, PolicyID combination the policy is considered to be new and entered into the cache.
For a value of 'D' (Deleted) the processor must find the associated object in its cache for the supplied DescriptorID PolicyID combination and eject it.
For each update the processor MUST operate on ALL changes to a descriptorID that have occured in the current update cycle. Once all changes to a specified descriptorID have been processed they should be inserted into the PDP wide AuthzCache. This should be done by exclusive lock and steps taken to minimise the time this lock is in effect.
A request supplying the descriptorID MUST be sent to the SPEP processor endpoint resolver for cache clear to retrieve a vector of endpoints to communicate with.
For each effected descriptorID/endpoint combination a ClearAuthzCacheRequest SHOULD be created by generating a base [Request] with the addition of the following:
Reason MUST be set to the string of "ESOE advises administrator initiated change to SPEP authzPolicy cache"
<Extenstions> MUST be present and its value MUST be set to be the set to the <GroupTarget> for this entity as follows:
The value of <GroupTargetID> SHOULD be set to the corresponding value of the entities <Policy> / <Target> from the authzCache. A new <AuthzTarget> element should be set to the corresponding value of each defined <Rule> / <Target>. Where <Rule> has been created with no <Target> value the value of <Policy> / <Target> should be substituted. This MUST only occur once, subsequent <Rules> that DO NO define a <Target> can be ignored.
For each request generated the spring injected ESOEWS instance clear cache service should be called and the generated SAML message and currently processing endpoint supplied. A SAML response document MUST be returned. The SAML response contained should be validated and a status of urn:oasis:names:tc:SAML:2.0:status:Success assured. Where these conditions are not met or an exception is returned by ESOWES a bean implementing com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate must be created. The SAML request document must be stored at com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate.requestDocument, the current endpoint at com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate.endPoint. This bean should be supplied to the Spring IoC injected failed authz cache monitor.
The processor MUST now sleep for another configured time interval.
Failed Authz Cache Monitor
The failed cache monitor consistently looks at a repository of com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate beans. Once it reaches the end of the repository it MUST immediently start at the beginning and work its way back through again attempting to deliver updates to SPEPs. On startup the monitor is to be created in its own thread, this thread MUST continuously stay active until the shutdown of the system. Should it fail in some way it MUST be automatically recovered by the system.
For each bean stored in the repository the spring injected ESOEWS instance clear cache service should be called with com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate.requestDocument and com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate.endPoint supplied. A SAML response document MUST be returned. The SAML response contained should be validated and a status of urn:oasis:names:tc:SAML:2.0:status:Success assured. If this is the case the bean is ejected from the local repository.
If this check fails the value of com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate.TimeStamp should be evaluated. If it is older then the time configured as a maximum (default of 24hrs) the bean is ejected from the local repository.
Where these conditions are not met or an exception is returned by ESOWES the bean should remain in the local repository.
External systems will supply additional failed requests to be added to the repository at random intervals. When they are supplied the repository MUST be locked for both read and write access while the new data is added. For each bean placed into the repository the value of com.qut.middleware.esoe.pdp.cache.bean.FailedAuthzCacheUpdate.TimeStamp must be set to the current system time.
Providing cache information to new or restarted SPEP
When an SPEP starts up it will interact with the ESOE through backchannel communication. The com.qut.middleware.esoe.spep.SPEPProcessor will make a call to the authzCacheProcessor to advise this new service has come online. It MUST supply the unique id of the descriptor along with the value of the authzCacheIndex to respond to.
The details stored in cache for the unique descriptorID should be retrieved, A ClearAuthzCacheRequest SHOULD be created by generating a base [Request] with the addition of the following:
Reason MUST be set to the string of "ESOE advises configured cache details for new SPEP execution instance"
<Extenstions> MUST be present and its value MUST be set to be the set to the <GroupTarget> for this entity as follows:
The value of <GroupTargetID> SHOULD be set to the corresponding value of the entities <Policy> / <Target> from the authzCache. A new <AuthzTarget> element should be set to the corresponding value of each defined <Rule> / <Target>. Where <Rule> has been created with no <Target> value the value of <Policy> / <Target> should be substituted. This MUST only occur once, subsequent <Rules> that DO NO define a <Target> can be ignored.
For each request generated the spring injected ESOEWS instance clear cache service should be called and the generated SAML message supplied along with the values descriptorID and the value of the endpoint. A SAML response document MUST be returned. The SAML response contained should be validated and a status of urn:oasis:names:tc:SAML:2.0:status:Success assured. Where these conditions are not met the value com.qut.middleware.esoe.pdp.cache.PolicyCacheProcessor.result.Failure should be returned, otherwise com.qut.middleware.esoe.pdp.cache.PolicyCacheProcessor.result.Successful should be returned.
Authorization Processor
| Component Lead |
Andre Zitelli |
| Package |
com.qut.middleware.esoe.pdp.impl.* |
| Type |
AuthorizationProcessorImpl |
| Implemented Interfaces |
com.qut.middleware.esoe.pdp.AuthorizationProcessor |
| Exceptions |
InvalidRequestException, InvalidPrincipalException |
The authorization processor is the core policy decision processor. It is responsible for evaluating requests to resources at remote SPEP's and responding with allows or denies based on the policies which have been defined by the administrators of that site.
It MUST implement the interface com.qut.middleware.esoe.pdp.AuthorizationProcessor
Binding for communicating with SPEP
The ESOE should implement the saml-bindings-2.0 SAML over SOAP over HTTP Binding as their method of communication with the SPEP.
The ESOE should only ever send authorization responses over backchannel communication.
The ESOE should not set any additional HTTP header information.
The SAML response should be appropriately wrapped in a SOAP envelope and delivered to the HTTP endpoint for the SPEP.
Request processing rules
Verify the supplied value of com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData.requestDocument. If it does not validate this is a failure. A response <StatusCode> of urn:oasis:names:tc:SAML:2.0:status:AuthnFailed must be returned. A Deny LXACMLAuthzDecisionStatement SHOULD be created with a <StatusMessage> of "Invalid request format". The exception com.qut.middleware.esoe.pdp.exception.InvalidRequestException should be created and thrown.
As soon as any failure state is encounted due to either internal processing factors or external environmental factors a Deny LXACMLAuthzDecisionStatement MUST be generated.
The value of <Issuer> should be retrieved and stored at com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData.descriptorID.
The value of <Subject> should be determined and stored against com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData.subjectID.
The subjectID SHOULD be used with the the com.qut.middleware.esoe.sessions.Query.querySAMLSession query component to retrieve a com.qut.middleware.esoe.sessions.Principal. If the request throws an exception this should be caught. It MUST be considered a failure, a response <StatusCode> of urn:oasis:names:tc:SAML:2.0:status:AuthnFailed must be returned. A Deny LXACMLAuthzDecisionStatement SHOULD be created with a <StatusMessage> of "Principal specified has not been previously identified". The exception com.qut.middleware.esoe.pdp.exception.InvalidPrincipalException SHOULD be created and thrown.
The vector stored in the authzCache for com.qut.middleware.esoe.pdp.bean.AuthorizationProcessorData.descriptorID should be retrieved. The <Resource> / <Attribute> / <AttributeValue> value in the presented <LXACMLAuthzDecisionQuery> must now be evaluated against all policies <Target> / <Resources> / <Resource> / <AttributeValue> values present in this vector. Values should attempt to be matched by:
#. Exact string match on supplied <Resource> / <AttributeValue>.
#. Regex string match on supplied <Resource> / <AttributeValue>.
If no match is established the PDP falls through to the default state of the policy (standard configuration sets this to Deny) and generates the appropriate LXACMLAuthzDecisionStatement, The response <StatusCode> should be set to urn:oasis:names:tc:SAML:2.0:status:Success. The LXACMLAuthzDecisionStatement should be created with a <StatusMessage> of "No matching policy located falling through to default state of $1", where $1 specifies the current default operation mode of the policy of "Permit" or "Deny". The value com.qut.middleware.esoe.pdp.AuthorizationProcessor.result.Successful should be returned.
ALL the matching policies MUST be evaluated until either a "Deny" effect is determined or until all matching policies are exhausted.
For each policy ALL the policy rules MUST be evaluated until either a "Deny" effect is determined or until all rules are exhausted.
In order to send the SPEP the correct response a record of every policy target and every rule target that evaluates to "Permit" must be recorded. If the final result is Permit this information will be sent to the SPEP as obligations in <LXACMLAuthzDecisionStatement>. For a Rule that does not implement a Target but which evaluates to Permit the target of the policy must be registered. This MUST be recorded only once even if multiple matching Rules in the policy do not specify a Target.
To evaluate each <Rule> it must be determined if the one of the <Rule> / <Target> / <Resources> / <Resource> / <AttributeValue> matches the <AttributeValue> of the <Resource> defined in the presented <LXACMLAuthzDecisionQuery>. If the <Rule> / <Target> does not exist it is considered to be an automatic match state. If it does exist it must be evaluated in the following order:
#. Exact string match on supplied <Resource> / <AttributeValue>.
#. Regex string match on supplied <Resource> / <AttributeValue>.
If a <Rule> is considered to be a match then the <Condition> element MUST be evaluated. If the condition does not exist the value of Effect is immediently applied. Should the value be "Permit" the value of RuleId should be added to the successfully negotiated rule set for this policy. Should the value be "Deny" the PDP MUST generate an appropriate LXACMLAuthzDecisionStatement. The response <StatusCode> should be set to urn:oasis:names:tc:SAML:2.0:status:Success. The LXACMLAuthzDecisionStatement should be created with a <StatusMessage> of "Policy $1 located and rules evaluated, identified DENY state for principal on Rule $2. Rules evaluated $3. $4", $1 SHOULD be the current PolicyId, $2 should be the current RuleId, $3 should be all RuleId values that were successfully evaluated for the current policy before the Deny state was encountered, $4 should be all PolicyId values of policies which have already been successfully evaluated. A <GroupTarget> with <GroupTargetID> set to the matching resource target of the current policy and the value of <AuthzTarget> set to the value of the current rule should also be set. The value com.qut.middleware.esoe.pdp.AuthorizationProcessor.result.Successful should be returned.
If a <Condition> element does exist it should be treated as a boolean function. <Conditions> may include embeded <Conditions>, <Apply>, <AttributeValue> and <SubjectAttributeDesignator>. Child nodes should be evaluated as necessary to satisfy the input requirements of their parents.
The <Apply> element denotes application of a function to its arguments, thus encoding a function call. The following functions may be defined as appropriate for the FunctionId attribute of the <Apply> element
- or
- This function SHALL return "False" if it has no arguments and SHALL return "True" if at least one of its arguments evaluates to "True". The order of evaluation SHALL be from first argument to last. The evaluation SHALL stop with a result of "True" if any argument evaluates to "True", leaving the rest of the arguments unevaluated.
- and
- This function SHALL return "True" if it has no arguments and SHALL return "False" if one of its arguments evaluates to "False". The order of evaluation SHALL be from first argument to last. The evaluation SHALL stop with a result of "False" if any argument evaluates to "False", leaving the rest of the arguments unevaluated.
- not
- This function SHALL take one argument of data-type "http://www.w3.org/2001/XMLSchema#boolean". If the argument evaluates to "True", then the result of the expression SHALL be "False". If the argument evaluates to "False", then the result of the expression SHALL be "True".
- string-equal
- This function SHALL take two arguments of data-type "http://www.w3.org/2001/XMLSchema#string" and SHALL return an "http://www.w3.org/2001/XMLSchema#boolean". The function SHALL return "True" if and only if the value of both of its arguments are of equal length and each string is determined to be equal byte-by-byte according to the function "integer-equal". Otherwise, it SHALL return "False".
- string-regexp-match
This function decides a regular expression match. It SHALL take two arguments of "http://www.w3.org/2001/XMLSchema#string" and SHALL return an "http://www.w3.org/2001/XMLSchema#boolean". The first argument SHALL be a regular expression and the second argument SHALL be a general string.
- string-normalize-space
- The function will have a result of the identified <AttributeValue> being normalized by stripping off all leading and trailing white space
- string-normalize-to-lower-case
- The function will have a result of the identified <AttributeValue> having each of its uppercase characters converted to its lowercase equivalent.
The <AttributeDesignatorType> is the type for elements that identify attributes by name. All attributes are considered to be of type string, should an attribute not be available the bag will be considered empty.
The <SubjectAttributeDesignator> indicates to the PDP it should use the set of values for the matching attribute which we have already retrieved earlier from the Sessions Processor.
The result of the <Condition> is the result of the top level <Apply> element. If the condition is evaluated as being TRUE then the value of Effect for the rule is applied. Should the value be "Permit" the value of RuleId should be added to the successfully negotiated rule set for this policy. Should the value be "Deny" the PDP MUST generate an appropriate LXACMLAuthzDecisionStatement. The response <StatusCode> should be set to urn:oasis:names:tc:SAML:2.0:status:Success. The LXACMLAuthzDecisionStatement should be created with a <StatusMessage> of "Policy $1 located and rules evaluated, identified DENY state for principal on Rule $2. Rules evaluated $3. $4", $1 SHOULD be the current PolicyId, $2 should be the current RuleId, $3 should be all RuleId values that were successfully evaluated for the current policy before the Deny state was encountered, $4 should be all PolicyId values of policies which have already been successfully evaluated. A <GroupTarget> with <GroupTargetID> set to the matching resource target of the current policy and the value of <AuthzTarget> set to the value of the current rule should also be set. The value com.qut.middleware.esoe.pdp.AuthorizationProcessor.result.Successful should be returned.
If the condition is evaluated as being FALSE then the rule is discounted in this policy evaluation. At this stage any remaining rules for the policy must be evaluated.
Once all <Policy> objects are evaluated by the PDP if at least one "Permit" has been identified the PDP MUST generate an appropriate LXACMLAuthzDecisionStatement. The response <StatusCode> should be set to urn:oasis:names:tc:SAML:2.0:status:Success. The LXACMLAuthzDecisionStatement should be created with a <StatusMessage> of "Policies located and rules evaluated, identified PERMIT state for principal. $1", $1 SHOULD be all PolicyId values of policies which were successfully evaluated. For each policy that contained at least one <Rule> which evaluated to Permit a <GroupTarget> with <GroupTargetID> set to the matching resource target of the policy and the values of <AuthzTarget> set to the target of all the contained rules which evaluated to Permit. The value com.qut.middleware.esoe.pdp.AuthorizationProcessor.result.Successful should be returned.
If all <Policy> objects are exhausted without an explicit "Deny" or "Permit" Effect being encountered the PDP falls through to the default state of the policy (standard configuration sets this to Deny) and generates an appropriate LXACMLAuthzDecisionStatement, The response <StatusCode> should be set to urn:oasis:names:tc:SAML:2.0:status:Success. The LXACMLAuthzDecisionStatement should be created with a <StatusMessage> of "Policies located and rules evaluated but no explicit outcome detected falling through to default state of $2", $1 SHOULD specify the current default operation mode of the policy of "Permit" or "Deny". The value com.qut.middleware.esoe.pdp.AuthorizationProcessor.result.Successful should be returned.
Creating LXACMLAuthzDecisionStatement
The LXACMLAuthzDecisionStatement should be created to match the outcomes of the request processor.
Queries which are evaluated to Deny
Set the value of <Response> / <Result> / <Decision> to Deny
<AttributeValue> should be the original resource that was queried by the SPEP
Set the value of <Response> / <Result> / <Status> / <StatusMessage> to the value indicated by the request processor.
Set the value of <Response> / <Result> / <Obligations> to a new <Obligation> with values:
FullFillOn set to Deny
ObligationId set to lxacmlpdp:obligation:cachetargets
- <AttributeAssignment> should have an AttributeId of lxacmlpdp:obligation:cachetargets:updateusercache and DataType of http://www.w3.org/2001/XMLSchema#string*
. Its value should be set to that of the specified *<GroupTarget> in escaped markup format.
- Where multiple <GroupTarget> elements exist multple <AttributeAssignment> elements MUST be created for each one.
Queries which are evaluated to Permit
Set the value of <Response> / <Result> / <Decision> to Permit
<AttributeValue> should be the original resource that was queried by the SPEP
Set the value of <Response> / <Result> / <Status> / <StatusMessage> to the value indicated by the request processor.
Set the value of <Response> / <Result> / <Obligations> to a new <Obligation> with values:
FullFillOn set to Permit
ObligationId set to lxacmlpdp:obligation:cachetargets
- <AttributeAssignment> should have an AttributeId of lxacmlpdp:obligation:cachetargets:updateusercache and DataType of http://www.w3.org/2001/XMLSchema#string*
. Its value should be set to that of the specified *<GroupTarget> in escaped markup format.
- Where multiple <GroupTarget> elements exist multple <AttributeAssignment> elements MUST be created for each one.
<lxacml-context:Result
xmlns:group="http://www.qut.com/middleware/lxacmlGroupTargetSchema"
xmlns:lxacml="http://www.qut.com/middleware/lxacmlSchema"
xmlns:lxacml-context="http://www.qut.com/middleware/lxacmlContextSchema">
<lxacml-context:Decision>Permit</lxacml-context:Decision>
<lxacml-context:Status>
<lxacml-context:StatusMessage>
Policies located and rules evaluated. Identified PERMIT
state for principal.
{urn:qut:policy:complex:3,urn:qut:policy:complex:4}
</lxacml-context:StatusMessage>
</lxacml-context:Status>
<lxacml:Obligations>
<lxacml:Obligation
ObligationId="lxacmlpdp:obligation:cachetargets"
FulfillOn="Permit">
<lxacml:AttributeAssignment
AttributeId="lxacmlpdp:obligation:cachetargets:updateusercache">
<group:GroupTarget>
<group:GroupTargetID>
/default/*
</group:GroupTargetID>
<group:AuthzTarget><