Clients
Client configurations, aliases and URLs
When you configure a client by creating a <client:config>
section in a config.xml file you're actually creating a unique URL that the user can access that particular client from.
For example if you create a client config with the id of 'main'
<client:config id="main"> <title>My Super Client</title> <!-- other config content goes here --> </client:config>
The the users will be able to access the client using /weave/main.html
.
Similarly if you create a client config with the id 'test' or 'external' then direct URL would be /weave/test.html
and /weave/external.html
respectively.
The extensions .html
and .htm
can both be used to access the clients.
index.html and the default client
index.html
is a special page that's handled by Weave differently. For a start this is the page that will be displayed if they don't specify a client directly, that is, /weave/
will in fact display the equivalent content of /weave/index.html
.
Furthermore index.html does some additional processing depending upon who the user is and how many clients configurations you've created.
Ignoring security for a moment, assuming everyone has access to everything, if you only have a single client configured then index.html
will just forward the user to that one client, e.g. /weave/
will forward to /weave/index.html
, then /weave/index.html
will forward to /weave/main.html
(assuming the only client you have configured has the id of 'main').
If however you have multiple clients configured then if the user accesses index.html
, either directly or indirectly, then the user is presented with a page containing a list of the clients that are available, and they must choose a specific client that they want to access before the client proper will be loaded.
You can disable the display of a specific client in this list by setting publish
to false in the client config.
<client:config id="test"> <publish>false</publish> <title>My Test Client</title> <!-- other config content goes here --> </client:config>
Note that if this results in there only being a single published client available then the user will again be automatically redirected to that client.
You can also completely disable a client configuration by setting enable
to false.
<client:config id="test"> <enable>false</enable> <title>My Test Client</title> <!-- other config content goes here --> </client:config>
This is would be the equivalent of completely removing the client configuration from the config.xml file, and is useful for quickly removing access to a client without having to remove it from the .xml file.
Access control and index.html
Bringing security back into the picture alters the landscape slightly. Specifically in the situation where a client config has an ACL attached to it and the user does not pass the ACL check, then the user will not have access to that client config.
This could mean that the user is reduced to a single client config (assuming there is one other client config wither with an ACL that the user passes or it doesn't have an ACL at all) in which case they'll be directed to that config in the same way as they would if there were only one client config.
Or, if they have more than one client config accessible, after the ACL checks, then they'll again be presented with the page listing all available client, but the page will only display those clients that the user has access to (and that are published and enabled).
Finally, if they have no client configs accessible then they'll be directed to a login page.
<client:config id="test"> <acl>admin</acl> <title>My Test Client</title> <!-- other config content goes here --> </client:config>
Just because a client config has an ACL attached to it does not mean that a user will not be able to access that client config, either if they're logged on or not, since the ACL may specify that 'anonymous' users are acceptable.
In addition to displaying the list of available client the list page also includes a button that allows the user to login (this button will allow the user to logout if they're already logged in). This button will direct the user to the login.html
page, this is the same login page that the user would be directed to if they did not have access to any client configurations because of ACL's.
This page provides the user with an opportunity to login top gain access to the system if all clients are locked down and the user has not already been authenticated (for example by using NTLM authentication which generally occurs before the index.html
page is displayed).
Advanced access control with security.xml
Restricting anonymous access
There are two ways to restrict access to Weave so that a user has to be authenticated before they can access the system (well three if you count automatic login mechanisms like NTLM) the first is to use the information above and set an ACL for each client config that disallows access to anonymous users
<acl:acl id="authenticated"> <entry type="deny">anonymous</entry> <entry type="allow">*</entry> </acl:acl> <client:config id="main"> <acl>authenticated</acl> <title>My Super Client</title> <!-- other config content goes here --> </client:config> <client:config id="test"> <acl>authenticated</acl> <title>My Test Client</title> <!-- other config content goes here --> </client:config>
The other method is to use security.xml
to ensure that the user is authenticated before they can even access the system.
This is done using the FilterSecurityInterceptor
in security.xml
. By default the FilterSecurityInterceptor
supplied with Weave is configured to ensure that each user is at least an anonymous user, this is the lowest level of authentication and basically ensures that we at least have a user object to work with. Changing the objectDefinitionSource
in the FilterSecurityInterceptor
from IS_AUTHENTICATED_ANONYMOUSLY
to IS_AUTHENTICATED_FULLY
you cane ensure that the user is forced to authenticate (either via the login page or using non-interactive methods if they're setup) before they can get any further into the system.
<property name="objectDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=IS_AUTHENTICATED_ANONYMOUSLY </value> </property>
This section can even be extended to provide different levels of default authentication for different client configurations, for example to ensure the user logs in to access main.html
but allow anonymous access to everything else (this doesn't mean an anonymous user can access every other client config, just that that decision will be handled by the ACL's and not by security.xml
) you could do the following.
<property name="objectDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /main.html=IS_AUTHENTICATED_FULLY /**=IS_AUTHENTICATED_ANONYMOUSLY </value> </property>
Client access with roles in security.xml
In addition to IS_AUTHENTICATED_FULLY
and IS_AUTHENTICATED_ANONYMOUSLY
you can also include roles that the user must have before they can access a given client configuration.
<property name="objectDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /external.html=ROLE_EXTERNAL /main.html=IS_AUTHENTICATED_FULLY /**=IS_AUTHENTICATED_ANONYMOUSLY </value> </property>
Here it's assumed that when logging in the authenticated user will be granted the role ROLE_EXTERNAL
, which would then allow them to access the /weave/external.html
URL.
Note that the equivalent can be done in using ACL's attached to a client configuration.
<acl:acl id="external"> <entry type="allow">ROLE_EXTERNAL</entry> <entry type="deny">*</entry> </acl:acl> <client:config id="external"> <acl>external</acl> <title>My External Client</title> <!-- other config content goes here --> </client:config>
There's one difference between using these above two methods that restrict access to a client configuration (assuming that in the security.xml
version the client config doesn't also have an ACL attached, if it did then they're exactly the same), and that's when it comes to the display of the client list page.
The security.xml
version will display the external client as being available to the user (because it doesn't have an ACL attached, meaning that the user won't fail to to pass the ACL checks for that particular client) but when the user attempts to open the page they'll either be asked to login, if they're an anonymous user or be denied access if they're not.
So this generally means that the ACL methods is more user friendly in an environment where the most of the authentication is being handled by Weave, whereas the security.xml
methods can be more useful in environments where security is also being handled elsewhere and they user is never intended to see the listing page.
Filter chains
In addition to the FilterSecurityInterceptor
objectDefinitionSource
there's another location where the client URL can play a part in authentication in security.xml
, and that's in the FilterChainProxy
.
The filter chain proxy determines what steps will be taken when an browser request passes through the security system.
By default Weave is configured with two different filter chains, one for requests from the JavaScript code in the client and one for every other request. This is primarily done for error handling, where we want any errors to be presented to the user using a nice HTML page, but error in response to requests made by the JavaScript code should be in a format that it can interpret.
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /server/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,jsonExceptionTranslationFilter,filterInvocationInterceptor /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor </value> </property> </bean>
Here we can see the default filter chains, with the /server/*
handling requests from the JavaScript code, and the /
*
chain handling everything else.
This list can be supplemented to perform different actions depending upon what filters a request should be processed by based on the URL of the request, and in this case we're talking about client configuration access URL's, so we can adjust the list to include a different filter chain for a different client
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /server/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,jsonExceptionTranslationFilter,filterInvocationInterceptor /internal.html=httpSessionContextIntegrationFilter,ntlmProcessingFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor </value> </property> </bean>
Here we've added the ntlmProcessingFilter
to the filter chain for any requests to access /weave/internal.html
.
Additional filter chains can be added for other client configurations.