Introduction
 | IMPORTANT: sunRise (= authentication framework) is part of the scratchpad area
of the current Cocoon
release. This means it is not officially released yet. The API and functionality might change
before it is moved into the official release. Using this is at your own risk!
If you want to catch the latest status of these components check out Cocoon
from CVS and have a look at this upto-date documentation.
|
The central point for building a web application is sunRise. It is a
flexible module for authentication and user management. A user can be
legitimated using any information available via any source, e.g. a database or
LDAP. With this mechanism it is very easy and fast to use an exisiting user
management/authentication system.
Sitemap-Components
sunRise adds some actions to the sitemap: the sunRise-auth
action, the sunRise-login action, the sunRise-logout action
and the sunRise-loggedIn action. The sunRise-auth action gets
the configuration for sunRise and controlles the pipelines. The
sunRise-login and the sunRise-logout action control the
authentication the sunRiseLoggedIn action controlles the application
flow.
The use of sunRise and its components is described in the following
chapters.
User Authentication
One feature of sunRise is the user authentication. A resource can be
accessible for everyone or it can be protected using sunRise. The process of
requesting a resource can be described as follows:
-
The user request a resource (original resource).
-
sunRise checks if this resource is protected. If no protection
is specified, the response to the request is this original resource.
-
The resource is protected and sunRise checks, if the user is
authenticated to view it.
-
If the user is authenticated, the response is the original
resource. If not sunRise redirects to a special redirect-to resource. This
redirect-to resource is freely configurable and can for example contain
information about the unauthorized access and in addition a login form.
-
Using the login form an authentication resource can be called
with the corresponding user information (e.g. user id and password). This
authentication resource uses sunRise for the authentication process.
-
In case of a successful authentication sunRise can redirect to
the original resource (or to any configured start resource).
-
If the authentication failed another resource is invoked by
sunRise displaying information to the user.
This process is only one example for a use-case of sunRise. sunRise
can be configured for any authentication scheme. All resources are freely
configurable.
The sunRise handler
The basic object for authentication in sunRise is the sunRise
handler. It controlles the access to the resources. Each resource in the
sitemap can be related to exactly one sunRise handler. All resources belonging
to the same handler are protected in the same way. If a user has access to the
handler, the user has the same access rights for all resouces of this
handler.
Each sunRise handler needs the following mandatory
configuration:
-
A unique name.
-
The authentication resource which does the real
authentication.
-
The redirect-to resource where sunRise redirects to for any
unauthorized request.
Using a unique name for each handler (only alphabetical characters
and digits are allowed for the handler name), sunRise manages different
handlers. So various parts of the sitemap can be protected in different ways. A
resource can be protected by calling this handler using the sunRise-auth
action. The "sunRise-auth" action must be included in the pipeline of the
resource. It gets the handler information as a parameter:
 |  |  |
 |
<map:match pattern="protectedresource">
<map:act type="sunRise-auth">
<map:parameter name="handler" value="unique handler name"/>
<map:generate src="source/resource.xml"/>
</map:act>
...
</map:match>
|  |
 |  |  |
If the pipeline does not use the "sunRise-auth" action or the
parameter "handler" is missing, the resource is accessible by any user.
The redirect-to resource
If the requested resource is not accessible for the user, sunRise
redirects to a special redirect-to resource. This resource is a mandatory
configuration of the sunRise handler:
 |  |  |
 |
<action name="sunRise-auth" ...>
<handlers> <!-- Now follows the handlers configuration -->
<handler name="unique">
<redirect-to uri="cocoon://loginpage"/> <!-- The login resource -->
</handler>
</handlers>
</action>
|  |
 |  |  |
This redirect-to resource is an unprotected resource in the
sitemap. For tracking which resource was requested, the redirect-to resource
gets the request parameter "resource" with the value. In addition all
parameters specified inside the redirect-to tag of the handler
configuration are passed to the resource.
This redirect-to resource can contain a form for the user
authentication. This form should invoke the real login resource which is
described below.
The authentication process is done by the "sunRise-login" action.
The login resource contains this action:
 |  |  |
 |
<map:match pattern="login">
<map:act type="sunRise-login">
<map:parameter name="handler" value="unique"/>
<map:parameter name="parameter_userid" value="request:name"/>
<map:parameter name="parameter_password" value="request:password"/>
<map:redirect-to uri="authentication-successful"/>
</map:act>
<!-- authentication failed: -->
<map:generate src="auth_failed.xml"/>
<map:transform src="tohtml.xsl"/>
<map:serialize/>
</map:match>
|  |
 |  |  |
The "sunRise-auth" action uses the handler parameter to call the
authentication resource of this handler. This authentication resource needs to
know the information provided by the user. For each piece of information an own
parameter is created which name starts with "parameter_". So in the example
above, the authentication resource gets two parameters: userid and password. As
the values for these parameters were send by a form they need to be passed on
to the authentication resource. If you use "request:..." for the value of a
parameter, the sunRise-login action will pass the actual value of that request
parameter to the authentication resource.
If the user is not authenticated with this handler, sunRise calls
the authentication resource and passes it the parameters. If this
authentication is successful, the action returns an empty map and the sitemap
commands inside the map:act are executed. If the authentication fails, these
are skipped.
If the authentication is successful, a session object is created on
the server (if not already done).
The authentication resource
The last chapters described the authentication process but left out
details about the authentication itself. This chapter closes this gap.
The authentication can be done by different components:
-
A sitemap resource.
-
A distant resource, e.g. requested via HTTP.
-
A java class.
Using this flexible approach nearly any kind of authentication is
possible (e.g. database, LDAP). The authentication resource is another
mandatory configuration of the sunRise handler:
 |  |  |
 |
<action name="sunRise" ...>
<handlers> <!-- Now follows the handlers configuration -->
<handler name="unique">
<redirect-to uri="cocoon:raw://loginpage"/> <!-- The login resource -->
<authentication uri="cocoon:raw://authenticationresource"/>
</handler>
</handlers>
</action>
|  |
 |  |  |
If the authentication resource is a sitemap resource or a remote
resource, this resource is requested by sunRise with the given parameters from
the sunRise-login action (see previous chapter: parameters: userid and
password). In addition all parameters inside the authentication tag of
the handler configuration are passed to the resource. The response for this
resource must contain valid XML conforming to the following scheme:
 |  |  |
 |
<authentication>
<ID>value</ID>
<role>rolename</role> <!-- optional -->
<data>
... resource specific data for the user
</data>
</authentication>
|  |
 |  |  |
sunRise checks the response of the authentication resource for the
given scheme: the root node must be named "authentication" and one child called
"ID" must be present. In this case the authentication is successfull and
sunRise creates a sunRise session context and stores the XML inside.
The mandatory information inside this XML scheme, the "ID" tag, is
an unique identification for the given user inside the web application. The
"role" is optional and can for example be used for categorizing users and
displaying different functionality inside sunSpot (the sunShine portal
engine).
Using the "data" node the authentication resource can pass any
information of the user into the session object.
If the authentication is not successful, the resource must create
an XML with the root node "authentication". In addition a "data" node can be
added containing more information about the unsuccessful attempt. This data
node is then added inside the "login" tag of the login resource (see previous
chapter).
Logging out
The logout process is triggered by the "sunRise-logout"
action:
 |  |  |
 |
<map:act type="sunRise-logout">
<map:parameter name="handler" value="unique"/>
</map:act>
|  |
 |  |  |
This action logs the user out of the given handler and removes all
information about this handler stored in the session.
Working With subsitemaps
The common solution for sunRise and subsitemaps is to define the
handler (and therefore the sunRise action) in the main sitemap. The resources
in the subsitemap are then simply protected in the same way as if the action
were declared in the main sitemap. This makes moving resources from one sitemap
to the other very simple.
However, there is one drawback with this solution. After
you have started your server, make sure that first a resource using sunRise
from the main sitemap is invoked, before any of the subsitemap!
User Management
In addition to the authentication sunRise manages all kinds of
information belonging to the user in XML format. For this reason sunRise
creates an own session context called sunRise. All information is stored in
this context.
The authentication information (the "authentication" scheme retrieved
from the authentication resource) is stored in this context, so you can
retrieve and change the information using the sunShine transformer and the
usual getxml, setxml etc. commands, so we suggest you to read the sunShine
context document.
Getting information from the context
Each information from within the context is gettable using an XML
tag:
 |  |  |
 |
<sunshine:getxml context="sunRise" path="/authentication/ID"/> <!-- Get the ID -->
<sunshine:getxml context="sunRise" path="/authentication/data/username"/>
|  |
 |  |  |
The path expression is an absolute XPath-like expression where only
concrete nodes and attributes are allowed. The sunShine transformer replaced
the tag with the value of the first node found in the context, this can either
be text or XML.
Setting information in the context
Using another tag information can be stored into the
context:
 |  |  |
 |
<sunshine:setxml context="sunRise" path="/authentication/data/usersername">
Mr. Sunshine
</sunshine:setxml>
|  |
 |  |  |
Again the path is an absolute XPath-like expression where only
concrete nodes and attributes are allowed. If the requested node exists,
sunRise changes the value of that node. If the node does not exists, sunRise
adds it to the context with the given value.
The tag is removed from the resource.
Application Management
A very useful feature for building and maintaining web applications
is the application management of sunRise. It allows to configure different
applications and to manage the user data for these applications.
Configuring an Application
A "sunRise" application is related to one sunRise handler, so an
application is part of the sunRise handler configuration:
 |  |  |
 |
<action name="sunRise" ...>
<handlers>
<handler name="unique">
....redirect-to/authentication configuration
<applications> <!-- the applications for this handler -->
<application name="unique">
<load uri="loadapp"/> <!-- optional -->
<save uri="saveapp"/> <!-- optional -->
</application>
</applications>
</handler>
</handlers>
</action>
|  |
 |  |  |
A configuration for an application consists of a unique name (only
alphabetical characters and digits are allowed for the application name) and
optional load and save resources. The application configuration can contain
application specific configuration values for the various parts of the
application, e.g. information for a portal.
On a successful authentication sunRise invokes for each application
of the handler the load resource (if present). The content or result of the
load resource is stored into the session context.
The user does not always visit all sides or all applications at
once. So it is not necessary to load all applications in advance when not all
information is needed. Each application can specify if the data is loaded on
successful authentication or the first time needed:
 |  |  |
 |
....<application name="unique" loadondemand="true"/>...
|  |
 |  |  |
The load resource gets several parameters: all values of the
subnodes of the "authentication" node from the sunRise context (e.g. ID, role
etc.) and the parameter "application" with the unique name of the application.
This unique name must not contain one of the characters '_', ':' or '/'.
In addition the load and save resource get all parameters specified
inside the load / save tag of the handler configuration.
Configuring the resources
For managing the application sunRise needs to know to which
application a resource belongs. So in addition to the handler parameter the
sunRise action gets the application name as a second parameter:
 |  |  |
 |
<map:match pattern="protectedresource">
<map:action type="sunRise-auth">
<map:parameter name="handler" value="unique handler name"/>
<map:parameter name="application" value="unique application name"/>
<map:generate src="source/resource.xml"/>
...
</map:action>
</map:match>
|  |
 |  |  |
With this mechanism each application resource can easily access its
and only its information. If a resource has no "application" parameter it can
not access information of any application.
Getting, setting and saving application information
Analogue to the access of the authentication data a resource can
access its application data:
 |  |  |
 |
<sunshine:getxml context="sunRise" path="/application/username"/>
<sunshine:setxml context="sunRise" path="/application/shoppingcart"><item1/><item2/></sunRise:setxml>
|  |
 |  |  |
The path underlies the same restrictions and rules as always, but
it has to start with "/application/".
Module Management
In addition to the application management sunRise offers a facility
called module management. It enhances the application management by the
possibility to configure components for the application. For example sunSpot is
the sunShine portal engine. It needs information about where the portal profile
for the user is retrieved from, where the layout is stored etc. Now each portal
needs this information. Assuming that a portal is an application each
application needs this sunSpot information. As only sunSpot itself knows what
information it needs, the module management is a standarized way for
configuring such components.
The module configuration is part of the application
configuration:
 |  |  |
 |
<action name="sunRise" ...>
<handlers>
<handler name="unique">
....redirect-to/authentication configuration
<applications> <!-- the applications for this handler -->
<application name="unique">
...
<configuration name="sunSpot">
...sunSpot configuration
</configuration>
</application>
</applications>
</handler>
</handlers>
</action>
|  |
 |  |  |
So whenever the module sunSpot is asked to build the portal it can
easily retrieve its configuration from the current application by getting the
module configuration named "sunSpot".
sunRise User Administration
Using sunRise it is possible to add new roles to the system and to
add new users. For this purpose, there are several optional entries for the
sunRise handler which provide the needed functionality:
 |  |  |
 |
<action name="sunRise" ...>
<handlers>
<handler name="unique">
...redirect-to/authentication configuration...
<!-- Optional resource for loading user information -->
<load-users uri="cocoon:raw://financeresource-sunrise-loaduser"/>
<!-- Optional resource for loading roles information-->
<load-roles uri="cocoon:raw://financeresource-sunrise-roles"/>
<!-- Optional resource for creating a new user -->
<new-user uri="cocoon:raw://financeresource-sunrise-newuser"/>
<!-- Optional resource for creating a new role -->
<new-role uri="cocoon:raw://financeresource-sunrise-newrole"/>
<!-- Optional resource for changing user information -->
<change-user uri="cocoon:raw://financeresource-sunrise-newuser"/>
<!-- Optional resource for deleting a role -->
<delete-role uri="cocoon:raw://financeresource-sunrise-delrole"/>
<!-- Optional resource for deleting a user-->
<delete-user uri="cocoon:raw://financeresource-sunrise-deluser"/>
</handler>
</handlers>
</action>
|  |
 |  |  |
The entries are described in the following subchapters. All tags can
have additional parameter definitions which are passed to the given resource,
e.g:
 |  |  |
 |
<!-- Optional resource for deleting a user-->
<delete-user uri="cocoon:raw://financeresource-sunrise-deluser">
<connection>database</connection>
<url>db:usertable</url>
</delete-user>
|  |
 |  |  |
Getting Roles
The load-roles resource is invoked from sunRise whenever
it needs information about the available roles. This resource gets the
parameter "type" with the value "roles" and should deliver an XML schema with
the root node "roles" and for each role a subelement "role" with a text child
of the rolename:
 |  |  |
 |
<roles>
<role>admin</role>
<role>guest</role>
<role>user</role>
</roles>
|  |
 |  |  |
Getting Users
The load-users resource is called whenever information
about the available users is needed. There are three different uses of this
resource:
-
Loading all users: The resource gets the parameter "type"
with the value "users". It should then deliver all users in the system.
-
Loading all users of one role. The resource gets the
parameters "type" with the value "users" and "role" with the rolename.
-
Load information of one user. The resource gets the
parameters "type" with the value "user", "role" with the rolename and "ID" with
the sunRise ID of the user.
The XML format of the resource should look like the
following:
 |  |  |
 |
<users>
<user>
<ID>sunRise ID</ID>
<role>rolename</role>
<data> ... application specific data ... </data>
</user>
<user>
...
</user>
...
</users>
|  |
 |  |  |
Creating a new role
The new-role resource creates a new role in the system. It
gets the parameters "type" with the value "role" and "role" with the new
rolename.
Creating a new user
The new-user resource creates a new user with a role. It
gets the parameters "type" with the value "user",
"role" with the rolename and "ID" with the new ID for this
user.
The sunrise transformer offers a tag to create a newuser:
"adduser". The input for this element is all information needed to add
a user including the ID and the role. All these values are then passed on to
the "new-user" resource:
 |  |  |
 |
<adduser>
<ID>New ID for this user</ID>
<role>The role</role>
<!-- and now application specific information in the following form:
<name_of_the_information>value</name_of_the_information>
-->
<firstname>x</firstname>
<lastname>y</lastname>
...
</adduser>
|  |
 |  |  |
In the example above a sunRise tries to create a new user with the
given "ID" and "role". The "new-user" resource gets
also the parameters "firstname" and "lastname" with the
values "X" and "Y".
If no user with this ID exists the "sunrise:adduser" element is
replaced with the element "success". Inside this element all the values are
repeated inside the "values" element:
 |  |  |
 |
<success>
<values>
<ID>New ID for this user</ID>
<role>The role</role>
<firstname>x</firstname>
<lastname>y</lastname>
</values>
</success>
|  |
 |  |  |
If a user already exists with this ID the response looks like
this:
 |  |  |
 |
<error>
<id-exists/>
<values>
<ID>New ID for this user</ID>
<role>The role</role>
<firstname>x</firstname>
<lastname>y</lastname>
</values>
</error>
|  |
 |  |  |
If an error occurs the response is this:
 |  |  |
 |
<error>
<exception/>
<values>
<ID>New ID for this user</ID>
<role>The role</role>
<firstname>x</firstname>
<lastname>y</lastname>
</values>
</error>
|  |
 |  |  |
Changing information of a user
The change-user resources changes information of a user.
It gets the parameters "type" with the value "user", "role" with the rolename
and "ID" with the ID of the user. In addition all - application specific -
information of this user is send as parameters.
Delete a user
The delete-user resource should delete a user. It gets the
parameters "type" with the value "user", "role" with the rolename and "ID" with
the ID of the user.
Delete a role
The delete-role resources deletes a role. It gets the
parameters "type" with the value "role" and "role" with the rolename .
sunRise Configuration Summary
Here is a brief summary of the sunRise handler configuration:
 |  |  |
 |
<action name="sunRise" ...>
<handlers>
<handler name="unique">
<redirect-to uri="cocoon:raw://loginpage"/> <!-- The redirect-to resource -->
<!-- Authentication resource -->
<authentication uri="cocoon:raw://authenticationresource">
<!-- optional parameters -->
</load>
<!-- optional save resource -->
<save uri="cocoon:raw://authenticationsaveresource">
<!-- optional parameters -->
</save>
<applications> <!-- the applications for this handler -->
<application name="unique">
<!-- Loading/Saving -->
<load uri="cocoon:raw://loadapp"> <!-- optional -->
<!-- optional parameters -->
</load>
<save uri="cocoon:raw://saveapp"> <!-- optional -->
<!-- optional parameters -->
</save>
<!-- module configurations: -->
<configuration name="sunSpot">
...sunSpot configuration
</configuration>
</application>
</applications>
</handler>
</handlers>
</action>
|  |
 |  |  |
Pipeline Patterns
As explained in the previous chapters, sunRise uses the sunRise
action for authentication and protecting resources. This chapter shows some
common used patterns of the pipelines for using sunRise.
Single protected resource
For protecting a resource with a sunRise handler only the sunRise
action with the parameter configuration for the handler is required.
Pattern:
-
Pipeline matching
-
Using the sunRise-auth action for protecting
Example:
 |  |  |
 |
<map:match pattern="protected">
<map:act type="sunRise-auth"> <!-- protect the resource -->
<map:parameter name="handler" value="myhandler"/>
<map:generate src="resource.xml"/>
<map:transform src="toHTML"/>
<map:serialize/>
</map:act>
</map:match>
|  |
 |  |  |
It is very important that the sunRise action wrapps the real
pipeline, as the pipeline is only invoked if the action grants access. The
matching must be done before the action is checked as the action performs a
redirect for this resource.
Multiple protected resources
Often you want to protect a bunch of resources in the same way. One
solution is to use the single protected resource pattern for each resource.
With the multiple protected resource pattern you only have to use the action
once for all resources and not within each resource.
The prerequisite for this is a common pattern for the
resources:
-
Pipeline pattern matching
-
Using the sunRise action for protection
-
Pipeline matching
Example:
 |  |  |
 |
<map:match pattern="protected-*">
<map:act type="sunRise-auth"> <!-- protect the resource -->
<map:parameter name="handler" value="myhandler"/>
<map:match pattern="protected-first">
<map:generate src="resource1.xml"/>
<map:transform src="toHTML"/>
<map:serialize/>
</map:match>
....
<map:match pattern="protected-second">
<map:generate src="resource2.xml"/>
<map:transform src="toHTML"/>
<map:serialize/>
</map:match>
</map:act>
</map:match>
|  |
 |  |  |
Very important - as explained with the single resource pattern - is
the leading match before the action is performed. The second match is required
to check which pipeline to use.
Controlling the Application Flow
If you want to create resources which behave different wheather you
are logged in or not, the sunRiseLoggedIn action is the component to
controll your application flow. This action checks if the user is authenticated
for a given handler and calls all sitemap components inside the act
tag.
 |  |  |
 |
<map:match pattern="startpage">
<map:act type="sunRise-loggedIn"> <!-- check authentication -->
<map:parameter name="handler" value="myhandler"/>
<map:redirect-to uri="loggedInStartPage"/>
</map:act>
<map:generate src="startpage.xml"/>
<map:transform src="toHTML"/>
<map:serialize/>
</map:match>
|  |
 |  |  |
In the example above, if the user is already logged he is
redirected to the loggedInStartPage resource. If he is not logged in
for the given handler, the usual start page is generated.
Both actions, the sunRise-auth and the
sunRise-loggedIn action return - if the user is logged in for the
given handler - all values from the context to the sitemap, e.g. ID, role etc.
These values can be used within the other components:
 |  |  |
 |
<map:match pattern"protected">
<map:act type="sunRise-auth"> <!-- protect the resource -->
<map:parameter name="handler" value="myhandler"/>
<!-- Append the ID of the user to the file name -->
<map:generate src="resource_{ID}.xml"/>
<map:transform src="toHTML"/>
<map:serialize/>
</map:act>
</map:match>
|  |
 |  |  |
But the sunRise-loggedIn action does not give the included pipeline
access to the sunRise context belonging to the handler. If you want this, you
have to nest the sunRise action inside!
 |  |  |
 |
<map:match pattern"start">
<map:act type="sunRise-loggedIn"> <!-- check authentication -->
<map:parameter name="handler" value="myhandler"/>
<map:act type="sunRise-auth"> <!-- give access to the context -->
<map:parameter name="handler" value="myhandler"/>
<map:generate src="getinfofromcontext.xml"/>
<map:transform src="sunRise"/>
<map:transform src="toHTML"/>
<map:serialize/>
</map:act>
</map:act>
</map:match>
|  |
 |  |  |
|