Hi
I've been looking recently at extending the CXF WS-Security component such
that a current UsernameToken could be used by custom interceptors
to authenticate a user with the external security systems and, if possible,
provide enough information for CXF to populate a SecurityContext [1] to be
used later on for
authorization decisions.
Here is the approach I've taken so far.
A custom interceptor extends
AbstractWSS4JSecurityContextProvidingInterceptor [2] and the only method it
overrides is
abstract Subject createSubject(String name, String password, boolean isDigest,
String nonce,
String created) throws WSSecurityException;
For example, see [3].
The idea here is that a custom interceptor interfaces whichever way it needs
to with the external system and populates a Subject following this simple
rule : first Subject principal is the current user (identified by a 'name'
argument), followed by one or more Groups this user is a member of.
AbstractWSS4JSecurityContextProvidingInterceptor will use this Subject to
provide a functional SecurityContext instance.
This is the first part, next is how to utilize a SecurityContext and get the
expected roles associated one way or the other with a current method to be
invoked. There's a number of usual options available here, perhaps even
SpringSecurity can be used now that SecurityContext is available, or
application code or other custom CXF interceptor can check the known roles
against SecurityContext.
I've also added AbstractAuthorizingInInterceptor interceptor which custom
interceptors can override and return a list of expected roles given a
(service) Method to be invoked upon, AbstractAuthorizingInInterceptor will
then ask available SecurityContext to match the roles; one concrete
implementation is SimpleAuthorizingInterceptor[5], it can be injected with a
method specific or class (applying to all methods) roles. Another
implementation which I will likely add later on will be injected with a name
of annotation such as RolesAlloved and it will introspect a method and its
class.
Note that I haven't looked into the case when a policy runtimes adds the
interceptors yet (as opposed to interceptors being configured form
Spring/programmatically). I think an optional contextual property will need
to be setup in such cases for users be able to indicate that say an
interceptor such as [3] has to be used as opposed to WSS4JInInterceptor,
etc.
I'm going to validate this approach with JBoss CXF. If you have any comments
then please let me know.
I think we may have a simpler alternative eventually to the way
authorization decisions are made. [1]-[3] is specific to ws-security, but
[4]-[5] is not
cheers, Sergey
[1] https://issues.apache.org/jira/browse/CXF-2754
[2]
http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
[3]
http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
[4]
http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
[5]
http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java