Sergey,

I think this type of functionality would be very useful to a number of
folks.  I have built two similar capabilities for clients very recently
using CXF and Spring Security.  Based on the code provided below, I have
several points that I would like to see addressed in a solution.

1) Architecture to support more than just UsernameTokens.  I have worked
with systems that need to authenticate a user using UsernameTokens,
BinarySecurityTokens, SAML Assertions, and a combination of more than one of
these at a time.  For the most part, WSS4J simply validates the structural
details of security.  That is, signature validity, trust chaining of digital
certificates, etc.  As Glen pointed out with his reference to
https://issues.apache.org/jira/browse/WSS-183, WSS4J sometimes performs its
own password checking (authentication).  Unfortunately, WSS4J doesn't
provide hooks for authenticating other forms of credentials that I have
listed above (I don't consider trust to be equivalent to authentication).
It would be best if the authentication interface supported multiple
credential types and allowed for authentication to be performed in a single
location in the same manner every time (not sometimes in the WSS4J callback
and sometimes in another interceptor for non-UT based credentials).  That
last bit there means disabling WSS4J's password authentication since it gets
in the way of doing it later in our own interceptor.

2) Allow for end-user flexibility in choosing the credentials they want to
authenticate.  For instance, each user is going to have their own security
profiles and authentication requirements.  For instance, a message contains
a UT for a portal user and a digital signature from the portal (I know using
a SAML Assertion would be better here, but people still do it this way).
Each organization will have different requirements as to which credentials
get authenticated and what needs to end up in the security context.

3) Decouple the authentication interface from WSS4J.  What is passed in
needs to be abstracted enough that it can work with other WS-Security
libraries as well.

4) It would be nice to be able to perform authorization using something like
Spring Security at the service operation level.  With a POJO or JAX-WS based
service, one can just use Spring Security's method interceptor to provide
such security; however, in situations where one only has a WSDL based
service or a provider style service, a method interceptor can't be used.  It
would be nice to provide a hook into Spring Security to allow end-users to
specify role based authorization policy based on a combination of interface,
instance, and operation names.  It seems like your
AbstractAuthorizingInterceptor and SimpleAuthorizingInterceptor are looking
in this direction, but I think it would be best if we can stand on the
shoulders of the Spring Security giant as much as possible so that we can
take advantage of their rich authorization manager, voter, XML configuration
capabilities.

5) Try not to leave the ServiceMix CXF-BC out in the cold.  The CXF-BC
currently has a limited capability to select the credentials to authenticate
and would benefit from 1 and 2 above.  The CXF-BC ultimately delegates
authentication to the JBI container through a ServiceMix components
authentication service abstraction of JAAS.  Whatever solution we have for 1
and 2 would help out the component if the ServiceMix authentication service
abstraction could be wired up in lieu of whatever we provide out of the box.


-----Original Message-----
From: Sergey Beryozkin [mailto:sberyoz...@gmail.com] 
Sent: Wednesday, April 07, 2010 10:11 AM
To: dev@cxf.apache.org
Subject: Using WS-Security UsernameToken to authenticate users and populate
SecurityContexts

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/a
pache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor
.java
[3]
http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/test/java/org/a
pache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
[4]
http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/c
xf/interceptor/security/AbstractAuthorizingInInterceptor.java
[5]
http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/c
xf/interceptor/security/SimpleAuthorizingInterceptor.java

Reply via email to