Hi I've added an initial patch for addressing a policy-first case, see [1]. It's a patch because it depends on another one I submitted to WSS4J [2]. Both patches need more work (tests, etc) but I'd just like to initiate a discussion/review.
The idea behind [1] is quite similar to the one used in supporting a java-first case, where a custom interceptor extends an AbstractWSS4JSecurityContextPr oviding interceptor. But is is much simpler in [1] where UsernameTokenProcessor may be optionally extended and its createSubject method be overridden. Provided [2] gets applied then a subclass will just have a property set disabling the (WSS4J) validation of passwords and will do its own validation in createSubject method. This is really all what will be needed in simple cases, where a DefaultSecurityContext will do, but optionally, createSecurityContext can be overridden too. A user would need to set a bus property "org.apache.cxf.ws.security.usernametoken.interceptor" referincing a custom interceptor which will indicate to the WSSecurityPolicyLoader that a custom UsernameTokenProcessor subclass will need to be loaded. Similar approach can be employed for handling other types of tokens. cheers, Sergey [1] https://issues.apache.org/jira/browse/CXF-2754 [2] https://issues.apache.org/jira/browse/WSS-229 On Mon, Apr 19, 2010 at 1:43 PM, Sergey Beryozkin <[email protected]>wrote: > Just realized I did not CC tp dev when replying to Dan the other day : > > Hi Dan > > > On Fri, Apr 9, 2010 at 2:50 PM, Daniel Kulp <[email protected]> wrote: > >> >> My main "concern" with the implementation of this is that it's done as a >> direct subclass of the WSS4JInInterceptor and thus not really usable by >> the >> policy based endpoints as those interceptors subclass WSS4JInInterceptor >> as >> well. >> >> I think the better approach may be to add a flag to wss4j (I can help >> commit >> changes there if needed) to have it not do any UserName token processing >> at >> all. (aside: this may be doable without changes to wss4j by registering >> our >> own "do nothing processor") Then, have another interceptor that runs >> after >> the WSS4JInInterceptor that would actually handle the UsernameToken and >> verify >> anything it needs and such. >> > > This sounds like a very good idea, I agree the proposed approach won't do > for the cases where policies drive the > creation of interceptors. > > Having said that, I think the abstract utility interceptor extending > WSS4JInInterceptor > may still be used in cases where users start from manually configuring > jaxws endpoints. In these cases they'd need to > list up to 3 interceptors (the one which extends > AbstractWSS4JSecuriyContextInterceptor, the authorizing interceptor if the > authorization is needed plus may be a SAAJ one) but otherwise, when say a > clear text password has been encrypted, they'd still need to specify > WSS4JInInterceptor (with a flag disabling UsernameToken checks) plus > UsernameTokenInterceptor, etc. > > At the moment AbstractWSS4JSecuriyContextInterceptor is a bit complicated > due to the fact it blocks the WSS4J digest checks and thus also creates a > security engine per every request, but it all will be gone in due time... > > >> >> To be honest, I WANT to do this for the Policy based stuff anyway. There >> is >> currently some duplicated code between the PolicyBasedWSS4JIinInterceptor >> and >> the new UsernameTokenInterceptor that could be eliminated by having the >> PolicyBasedWSS4JIinInterceptor not do UsernameTokens at all and delegate >> that >> completely to the UsernameTokenInterceptor. >> > > What I will do is I will experiment with the test you added (thanks :-)) > and see how UsernameTokenInterceptor can be refactored > so that a subclass can get an easy access to password, nonce, etc. I think > I will need to come up with a contextual property so that a custom > UsernameTokenInterceptor can be installed if needed. Or may be > UsernameTokenInterceptor can store the details in a message to be later > retrieved and processed for creating SecurityContext - but I'm not sure > about it just yet. > > >> >> Basically, it would be good if the WSS4JIn* stuff just handled the >> encryption/signature stuff and then let the authorization validations >> stuff to >> later interceptors. That would include things like key validation >> checking >> and stuff as well. Probably SAML token validation as well. >> >> > sounds good > > cheers, Sergey > > On Fri, Apr 9, 2010 at 2:50 PM, Daniel Kulp <[email protected]> wrote: > >> >> My main "concern" with the implementation of this is that it's done as a >> direct subclass of the WSS4JInInterceptor and thus not really usable by >> the >> policy based endpoints as those interceptors subclass WSS4JInInterceptor >> as >> well. >> >> I think the better approach may be to add a flag to wss4j (I can help >> commit >> changes there if needed) to have it not do any UserName token processing >> at >> all. (aside: this may be doable without changes to wss4j by registering >> our >> own "do nothing processor") Then, have another interceptor that runs >> after >> the WSS4JInInterceptor that would actually handle the UsernameToken and >> verify >> anything it needs and such. >> >> To be honest, I WANT to do this for the Policy based stuff anyway. There >> is >> currently some duplicated code between the PolicyBasedWSS4JIinInterceptor >> and >> the new UsernameTokenInterceptor that could be eliminated by having the >> PolicyBasedWSS4JIinInterceptor not do UsernameTokens at all and delegate >> that >> completely to the UsernameTokenInterceptor. >> >> Basically, it would be good if the WSS4JIn* stuff just handled the >> encryption/signature stuff and then let the authorization validations >> stuff to >> later interceptors. That would include things like key validation >> checking >> and stuff as well. Probably SAML token validation as well. >> >> Dan >> >> >> On Thursday 08 April 2010 12:09:24 pm Sergey Beryozkin wrote: >> > Hi David >> > >> > thanks for the comments... >> > >> > On Wed, Apr 7, 2010 at 9:41 PM, David Valeri <[email protected]> >> wrote: >> > > 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. >> > >> > Supporting UsernameTokens is the initial requirement. At the moment I do >> > not even know how BinarySecurityTokens or SAML Assertions are >> > processed/validated in CXF or WSS4J. >> > >> > > 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). >> > >> > Makes sense. Assuming it is WSS4J which validates (the structure of) >> > BinarySecurityTokens then >> AbstractWSS4JSecurityContextProvidingInterceptor >> > can also implement a processor for BinarySecurityTokens and delegate to >> > subclass to authenticate and setup a subject. Some extra methods will >> need >> > to be added, to be optionally overridden. >> > >> > If it is not only WSS4J which is involved then perhaps another option is >> to >> > store (from WSS4J callback handler, etc) relevant details such username >> > token details, etc to be acted upon by other interceptors. >> > >> > > That >> > > last bit there means disabling WSS4J's password authentication since >> it >> > > gets >> > > in the way of doing it later in our own interceptor. >> > >> > AbstractWSS4JSecurityContextProvidingInterceptor does it now by >> > implementing a simplified UsernameTokenProcessor >> > >> > > 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. >> > >> > I suppose AbstractWSS4JSecurityContextProvidingInterceptor subclasses >> > should be able to do it, for username tokens and other tokens later on. >> > >> > > 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. >> > >> > the only WSS4J class which is leaked at the moment is >> WSSecurityException. >> > Perhaps we can come up later on with a different more generic approach >> > which does not depend on WSS4J at all. As Dan indicated, in some cases >> > WSS4JInInterceptor is not even used, so that case will need to be >> > addressed. Experimenting wuth binary tokens might help with identifying >> > another solution. >> > >> > > 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. >> > >> > Not sure what to say here yet. But I think non-Spring users should be >> taken >> > care of too. Or when simpler cases are dealt with then perhaps there's >> no >> > need to bring in Spring security. Perhaps the utility authorization >> > interceptors should just not be used when Spring Security is preferred ? >> > >> > > 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. >> > >> > I'm not planning to contribute to ServiceMix. I agree though that an >> ideal >> > solution will meet multiple requirements >> > >> > thanks, Sergey >> > >> > > -----Original Message----- >> > > From: Sergey Beryozkin [mailto:[email protected]] >> > > Sent: Wednesday, April 07, 2010 10:11 AM >> > > To: [email protected] >> > > 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/or >> > > g/a >> > > >> > > >> pache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingIntercep >> > > tor< >> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/jav >> > > >> a/org/a%0Apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidi >> > > ngInterceptor> .java >> > > [3] >> > > >> > > >> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/test/java/or >> > > g/a >> > > >> pache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java<http:/ >> > > / >> svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/test/java/org/a%0A >> > > pache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java> [4] >> > > >> > > >> http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apach >> > > e/c >> > > xf/interceptor/security/AbstractAuthorizingInInterceptor.java< >> http://svn >> > > . >> apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/c%0Axf/i >> > > nterceptor/security/AbstractAuthorizingInInterceptor.java> [5] >> > > >> > > >> http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apach >> > > e/c >> > > xf/interceptor/security/SimpleAuthorizingInterceptor.java< >> http://svn.apa >> > > >> che.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/c%0Axf/inter >> > > ceptor/security/SimpleAuthorizingInterceptor.java> >> >> -- >> Daniel Kulp >> [email protected] >> http://dankulp.com/blog >> > >
